bash:嵌套语句中的赋值和条件测试?

bash:嵌套语句中的赋值和条件测试?,bash,if-statement,nested,variable-assignment,side-effects,Bash,If Statement,Nested,Variable Assignment,Side Effects,我要寻找的是一行紧凑的代码,它在一个嵌套语句中两次使用表达式的值 对于变量的赋值,以及 对变量的新值与另一个值进行条件测试 问题是: 在bash中通常可以使用这种紧凑形式吗 如果是的话,我是否必须担心负面的副作用(意外的结果) 您当然可以在以下时间之前完成作业: $ local bus_connection="$(lsblk -dn -o TRAN /dev/sdd)" $ test "$bus_connection" = "usb" || { echo "not usb"; exit 1

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

  • 对于变量的赋值,以及

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

问题是:

  • 在bash中通常可以使用这种紧凑形式吗

  • 如果是的话,我是否必须担心负面的副作用(意外的结果)

  • 您当然可以在以下时间之前完成作业:

    $ 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'):

    在bash中,我尝试:

    $ test $(bus_connection="$(lsblk -dn -o TRAN /dev/sdd)") = "usb" || echo "not usb" 
    bash: test: =: unary operator exspected.
    not usb
    
    -->错误消息和错误结果

    $ echo "$bus_connection"
    0
    
    我用一个整数案例进行了测试,发现:

    $ 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”视为整数类型

    对字符串有什么建议吗

    在bash中通常可以使用这种紧凑形式吗

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

    通常的方法是用
    &&
    分配变量,然后是test-这允许检查命令的退出状态并获取结果

    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 nameference将第一个参数分配给第二个参数,并返回
    test
    s退出状态:

    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
    

    请注意,在这里,与第一个使用
    本地总线连接=$(…)
    的代码片段一样,命令替换的退出状态被忽略。

    要担心负面副作用,请定义“负面”。什么是“消极副作用”?是的,意外副作用。在这个组合中,我还看不到任何。但我可能错了,在某些情况下,结果并不像预期的那样。