我正在使用 Bash 3,并且正在尝试形成一个条件。在 C/C++ 中,它非常简单:((A || B) && C)
.在 Bash 中,结果并非如此(我认为 Git 作者在转向其他工作之前一定已经贡献了这段代码)。
这是行不通的。请注意,这<0 or 1>
不是一个字符串文字;它表示 0 或 1(通常来自grep -i
)。
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi
其结果是:
line 322: syntax error near unexpected token `[['
然后我尝试:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi
结果是:
line 322: syntax error near unexpected token `[['
部分问题是搜索结果是简单的示例,而不是具有复合条件的更复杂的示例。
如何((A || B) && C)
在 Bash 中执行简单操作?
我准备好展开它并在多个块中重复相同的命令:
A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then
...
elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then
...
fi
答案1
bash 的语法与 C 不同,即使其中一小部分受到 C 的启发。您不能简单地尝试编写 C 代码并期望它能够工作。
shell 的要点是运行命令。开括号命令[
是执行单个测试的命令。您甚至可以将其写为test
(不带最后的右括号)。||
和运算符&&
是 shell 运算符,它们组合起来命令,不是测试。
所以当你写的时候
[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]
被解析为
[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]
这与以下相同
test [ "$A" -eq "0" ||
test "$B" -ne "0" ] &&
test "$C" -eq "0"
注意到不平衡的括号了吗?是的,那不好。您对括号的尝试也有同样的问题:虚假括号。
将命令组合在一起的语法是大括号。解析大括号的方式需要在它们之前有一个完整的命令,因此您需要使用换行符或分号来终止大括号内的命令。
if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then …
还有一种替代方法是使用双括号。与单括号不同,双括号是特殊的 shell 语法。他们划定界限条件表达式。在双括号内,您可以使用括号和运算符,例如&&
和||
。由于双括号是 shell 语法,因此 shell 知道当这些运算符位于括号内时,它们是条件表达式语法的一部分,而不是普通 shell 命令语法的一部分。
if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …
如果您所有的测试都是数字的,那么还有另一种方法可以界定算术表达式。算术表达式使用非常类似于 C 的语法执行整数计算。
if (((A == 0 || B != 0) && C == 0)); then …
你可能会发现我的 bash 支架底漆有用。
[
可以在普通 sh 中使用。[[
并且((
特定于 bash(以及 ksh 和 zsh)。
1它还可以将多个测试与布尔运算符结合起来,但这使用起来很麻烦,并且有微妙的陷阱,所以我不会解释它。
答案2
使用[[
:
if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ...
如果您愿意[
,可以执行以下操作:
if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ...
答案3
使用-o
运算符而不是嵌套的 ||。-a
如果需要,您还可以在其他语句中使用 && 来替换。
EXPRESSION1 -a EXPRESSION2
both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2
either EXPRESSION1 or EXPRESSION2 is true
if [ "$A" -eq "0" -o "$B" -ne "0" ] && [ "$C" -eq "0" ]; then echo success;fi