【问题标题】:bash: assignment AND condition test in nested statement?bash:嵌套语句中的赋值和条件测试?
【发布时间】:2020-09-13 00:14:40
【问题描述】:

我正在寻找的是一个紧凑的代码行,它在一个嵌套语句中两次使用表达式的值

  • 对于变量的赋值

  • 变量的新值与另一个值的条件测试

问题是:

  1. 这种紧凑形式在 bash 中是否普遍可行?

  2. 如果是,我是否必须担心负面影响(意外结果)?

你当然可以先做任务:

$ local bus_connection="$(lsblk -dn -o TRAN /dev/sdd)"
$ test "$bus_connection" = "usb" || { echo "not usb"; exit 1 }
$ echo "$bus_connection"
usb

--> 有效!

如果只有在成功的情况下才需要变量“bus_connection”,你也可以这样做:

$ test "$(lsblk -dn -o TRAN /dev/$DEVICE)" = "usb" \
    && local bus_connection="usb" \
    || { echo "not usb"; exit 1 }
$ echo "$bus_connection"
usb

--> 也有效! (不要在命令行中使用“local”!)

在 C(++) 和其他一些已编译的高级语言中,您可以做得更紧凑(假设一个 c 函数 'lsblk'):

if( ( bus_connection = lsblk( ... ) ) == "usb" ) ; else {printf("not usb"); exit 1;}

我在 bash 中尝试过:

$ test $(bus_connection="$(lsblk -dn -o TRAN /dev/sdd)") = "usb" || echo "not usb" 
bash: test: =: unary operator exspected.
not usb

--> 错误信息和错误结果!

我用整数大小写测试发现:

$ sum=0
$ result=12
$ test $((sum=$sum+$result)) -gt 20 && echo "true"
$ test $((sum=$sum+$result)) -gt 20 && echo "true"
true

--> 有效!副作用?

类比:

$ test $((bus_connection="$(lsblk -dn -o TRAN /dev/sdd)")) = "usb" || echo "not usb"
not usb

--> 没有错误信息但结果错误!

$ echo "$bus_connection"
0

--> 啊,显然 bash 现在将变量 'bus_connection' 视为整数类型。

对字符串有什么建议吗?

【问题讨论】:

  • to fear negative side effects 请定义“否定”。什么是“负面影响”?
  • 是的,意外的副作用。在这个组合中,我还看不到任何东西。但我可能是错的,在某些情况下结果不符合预期。

标签: bash if-statement nested variable-assignment side-effects


【解决方案1】:

这种紧凑的形式在 bash 中是否普遍可行

不,它不是,至少不是没有自定义代码来处理它。命令替换在子 shell 中运行 - 更改在父 shell 中不可见。算术扩展只进行算术运算 - 所有字符串都转换为数字(就像 atoi()/strtol() 一样),如果没有扫描到数字,它们将转换为 0。

通常的方法是给变量赋值&&,然后是测试 - 允许检查命令的退出状态并获取结果。

if ! {
     bus_connection="$(lsblk -dn -o TRAN /dev/sdd)" &&
     test "$bus_connection" = "usb"
}; then
   echo "not usb"
   exit 1
fi

或者直接忽略lsblk的退出状态:

if
   bus_connection="$(lsblk -dn -o TRAN /dev/sdd)"
   ! test "$bus_connection" = "usb"
then
   echo "not usb"
   exit 1
fi

您仍然可以编写自己的函数,使用 bash 名称引用将第一个参数分配给第二个参数并返回 tests 退出状态:

test_and_assign() {
   declare -n _test_and_assign_ref=$1
   shift
   _test_and_assign_ref="$1"
   test "$@"
}

$ test_and_assign bus_connection "$(echo 123)" = "usb"
$ echo "$? $bus_connection"
1 123
$ test_and_assign bus_connection "$(echo usb)" = "usb"
$ echo "$? $bus_connection"
0 usb

请注意,在这里,就像在您的第一个带有local bus_connection=$(...) 的代码 sn-p 中一样,命令替换的退出状态将被忽略。

【讨论】:

    猜你喜欢
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 2017-12-24
    • 2012-02-17
    • 1970-01-01
    相关资源
    最近更新 更多