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
在我看来,当解释器寻找 1
s 时,它应该像这样工作:
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"
}
为什么?!我认为它会寻找 1
s,所以因为它在 &&
中找到 0
,所以它不会查看链中的其他表达式!
{...} 没有区别,所以你所拥有的等同于:
i=10
[ $i -lt 5 ] &&
echo "$i < 5" ||
[ $i -gt 5 ] &&
echo "$i > 5" ||
[ $i -eq 5 ] &&
echo "$i = 5"
它的工作方式是:
[ $i -lt 5 ]
:这是错误的(returns失败),所以它跳转到下一个||
,它后面有[ $i -gt 5 ]
。
[ $i -gt 5 ]
:这是真的(returns成功),所以它跳转到下一个&&
,它后面有echo "$i > 5"
。
echo "$i > 5"
: 这个 returns 成功,所以它跳转到下一个 &&
,它后面有 echo "$i = 5"
。
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
.
谜团解开了。
我想知道为什么
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
在我看来,当解释器寻找 1
s 时,它应该像这样工作:
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"
}
为什么?!我认为它会寻找 1
s,所以因为它在 &&
中找到 0
,所以它不会查看链中的其他表达式!
{...} 没有区别,所以你所拥有的等同于:
i=10
[ $i -lt 5 ] &&
echo "$i < 5" ||
[ $i -gt 5 ] &&
echo "$i > 5" ||
[ $i -eq 5 ] &&
echo "$i = 5"
它的工作方式是:
[ $i -lt 5 ]
:这是错误的(returns失败),所以它跳转到下一个||
,它后面有[ $i -gt 5 ]
。[ $i -gt 5 ]
:这是真的(returns成功),所以它跳转到下一个&&
,它后面有echo "$i > 5"
。echo "$i > 5"
: 这个 returns 成功,所以它跳转到下一个&&
,它后面有echo "$i = 5"
。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
.
谜团解开了。