【问题标题】:Shell : logical ANDs and ORs instead of if-elseShell:逻辑 AND 和 OR,而不是 if-else
【发布时间】:2015-09-29 17:27:39
【问题描述】:

我想知道为什么

i=10
  if [ $i -lt 5 ]; then
    echo "$i < 5"
elif [ $i -gt 5 ]; then
    echo "$i > 5"
elif [ $i -eq 5 ]; then
    echo "$i = 5"
fi

输出正确的结果:

10 > 5

i=10
     [ $i -lt 5 ] && {
    echo "$i < 5"
} || [ $i -gt 5 ] && {
    echo "$i > 5"
} || [ $i -eq 5 ] && {
    echo "$i = 5"
}

表现异常:

10 > 5
10 = 5

在我看来,当解释器寻找1s 时,它应该是这样工作的:

0 && {} || 1 && {} || 0 && {}

0 所以 0 && {} 肯定是 0;跳过{}

1 表示必须检查 {} 以定义整个 1 &amp;&amp; {} 的值

因此结果为 1,但唯一执行的{} 停留在1 之后。 但是,当我输入 ! { 而不是 {s 时,这一切都可以正常工作。

i=10
     [ $i -lt 5 ] && ! {
    echo "$i < 5"
} || [ $i -gt 5 ] && ! {
    echo "$i > 5"
} || [ $i -eq 5 ] && ! {
    echo "$i = 5"
}

为什么?!我认为它会寻找1s,所以因为它在&amp;&amp; 中找到了0,所以它不会查看链中的其他表达式!

【问题讨论】:

    标签: bash shell unix boolean zsh


    【解决方案1】:

    {...} 没有区别,所以你所拥有的就相当于:

    i=10
    [ $i -lt 5 ] && 
    echo "$i < 5" ||
    [ $i -gt 5 ] &&
    echo "$i > 5" || 
    [ $i -eq 5 ] &&
    echo "$i = 5"
    

    它的工作方式是:

    1. [ $i -lt 5 ]:这是假的(返回失败),所以它跳转到下一个||,它后面有[ $i -gt 5 ]

    2. [ $i -gt 5 ]:这是真的(返回成功),所以它跳转到下一个&amp;&amp;,后面有echo "$i &gt; 5"

    3. echo "$i &gt; 5":返回成功,因此跳转到下一个&amp;&amp;,后面有echo "$i = 5"

    4. echo "$i = 5":这会返回成功,所以它会跳转到...等等,不,有一个换行符。我们完成了。

    &amp;&amp;|| 称为短路运算符。

    编辑:为了进一步强调这一点,

    A && B || C
    

    相同
    if A; then
        B
    else
        C
    fi
    

    相当于

    if A; then
        if ! B; then
            C
        fi
    else
        C
    fi
    

    【讨论】:

    • 更具体地说,在shell中X &amp;&amp; Y || Z不是三元运算。
    • 为什么在下一个乘法(第3步)中会从1跳转到第二个表达式?
    • @theoden,命令成功后跳转到下一个&amp;&amp;。当命令失败时,它会跳转到下一个||。就是这么简单。 echo 返回 0(成功),所以它跳转到下一个 &amp;&amp;。正如@EtanReisner 提到的,a &amp;&amp; b || c if a; then b; else c; fi 相同
    • @geirha,该死的,我认为它有点复杂,就像它创建一个有序的二叉树并从左到右(从上到下)解析。我认为X &amp;&amp; Y || Z 的含义与X * Y + Z 相同。编辑:明白。谢谢。
    【解决方案2】:

    &amp;&amp;|| 从左到右进行评估。您的命令或多或少等同于:

    (((( false && { echo 1; true; } ) || true ) && { echo 2; true; } ) || false ) && { echo 3; true; }
    
    • false &amp;&amp; { echo 1; true; } 不打印任何内容,计算结果为 false
    • false || true 评估为 true
    • true &amp;&amp; { echo 2; true; } 打印 2 并计算为 true
    • true || false 计算为 true
    • true &amp;&amp; { echo 3; true; } 打印 3 并计算为 true

    谜团解开了。

    【讨论】:

    • 等等,算术上是对的,但是为什么A * B + C * D变成了(((A * B) + C) * D)?
    • @theoden 因为这些是列表运算符,并且根据 bash 手册:“[o]f 这些列表运算符,&amp;&amp;|| 具有相同的优先级,然后是 ;&amp;,它们具有相同的优先级”。意思是,如果您只有&amp;&amp;||,则严格从左到右对它们进行评估。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多