考虑两个条件表达式expr1
and expr2
,例如$i -eq $j
and $k -eq $l
。我们可以bash
通过多种方式来编写它。这里有两种可能
[[ expr1 || expr2 ]]
[[ expr1 ]] || [[ expr2 ]]
Run Code Online (Sandbox Code Playgroud)
我很确定我在这里看到了推荐第二个应该是首选的建议,但我找不到证据来支持这一点。
这是一个示例脚本,似乎表明没有区别:
for i in 0 1
do
for j in 0 1
do
for k in 0 1
do
for l in 0 1
do
if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yes\t"; else printf "1-no\t"; fi
if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yes\n"; else printf "2-no\n"; fi
done
done
done
done
Run Code Online (Sandbox Code Playgroud)
和输出显示两个条件构造产生相同的结果:
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-no 2-no
1-no 2-no
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
1-yes 2-yes
Run Code Online (Sandbox Code Playgroud)
使用一种构造比使用另一种构造有什么好处吗?
对于奖励积分,同样的问题,但使用||
和概括为多个条件&&
。例如,[[ expr1 && expr2 || expr3 ]]
。
我认为您看到的建议是针对 POSIX sh和/或test
兼作[
命令的命令,而不是[[
出现在 ksh 中的构造(感谢 Stéphane Chazelas 的提示)并且还用于例如 bash、zsh 和其他一些贝壳。
在大多数语言中,如 C,当一个子句已知为真或假时,不需要根据操作评估剩余部分:如果真不在逻辑之后或在它之后,如果假不在逻辑和之后,等等。这当然允许例如在指针为 NULL 时停止,而不是尝试在下一个子句中取消引用它。
但是sh的[ expr1 -o expr2 ]
构造(包括 bash 的实现)并没有这样做:它总是评估双方,当人们只希望评估expr1 时。这样做可能是为了与test
命令实现兼容。另一方面, sh||
和&&
确实遵循通常的原则:如果不会改变结果,则不进行评估。
所以要注意的区别是:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
Run Code Online (Sandbox Code Playgroud)
产生:
true
or-was-evaluated
Run Code Online (Sandbox Code Playgroud)
上面,每个都[
可以替换为/usr/bin/[
which 是test
命令的别名,之前使用的[
是内置到 shell 中。
而接下来的两个构造:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
Run Code Online (Sandbox Code Playgroud)
或者
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Run Code Online (Sandbox Code Playgroud)
只会让步true
并effect
留空:||
行为正确,并且也[[
更正了这个问题。
更新:
正如@StéphaneChazelas 所评论的,我错过了与最初问题相关的几个不同之处。我将把最重要的一项(至少对我而言)放在这里:运营商的优先级。
虽然 shell 不会考虑优先级:
if true || true && false; then
echo true
else
echo false
fi
Run Code Online (Sandbox Code Playgroud)
产生(因为没有优先级,因此首先true || true
评估,然后&& false
):
false
Run Code Online (Sandbox Code Playgroud)
运算符内部[[ ]]
的&&
优先级高于||
:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
Run Code Online (Sandbox Code Playgroud)
产量(因为1 -eq 1 && 1 -eq 0
被分组,因此是 的第二个成员||
):
true
Run Code Online (Sandbox Code Playgroud)
至少对于ksh,bash,zsh。
所以[[ ]]
拥有既提高了性能[ ]
和直接壳逻辑运算符。
归档时间: |
|
查看次数: |
564 次 |
最近记录: |