Shell : 逻辑 AND 和 OR 而不是 if-else

Shell : logical ANDs and ORs instead of if-else

我想知道为什么

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 so the 0 && {} is definitely 0; skip {}

1 means that {} must be checked to define the value of whole 1 && {}

所以结果是1,但是只执行{}留在1之后。 但是,当我将 ! { 而不是 {s.

时,这一切都可以正常工作
i=10
     [ $i -lt 5 ] && ! {
    echo "$i < 5"
} || [ $i -gt 5 ] && ! {
    echo "$i > 5"
} || [ $i -eq 5 ] && ! {
    echo "$i = 5"
}

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

{...} 没有区别,所以你所拥有的等同于:

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

它的工作方式是:

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

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

  3. echo "$i > 5": 这个 returns 成功,所以它跳转到下一个 &&,它后面有 echo "$i = 5"

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

&&||被称为短路运算符。

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

A && B || C

不同
if A; then
    B
else
    C
fi

相当于

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

&&|| 从左到右求值。您的命令或多或少等同于此:

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

谜团解开了。