经典技巧(转义元字符):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
我已将对$g 的引用用双引号括起来;一般来说,这是一个很好的做法。严格来说,不需要括号,因为 -a 和 -o 的优先级即使没有它们也可以正确。
请注意,-a 和 -o 运算符是 test 的 POSIX 规范的一部分,也称为 [,主要是为了向后兼容(因为它们是第 7 版 UNIX 中 test 的一部分,对于例如),但它们被 POSIX 明确标记为“过时”。 Bash(参见 conditional expressions)似乎抢占了 -a 和 -o 的经典和 POSIX 含义,并使用其自己的带参数的替代运算符。
请注意,您可以使用更现代的[[ 运算符,但请注意,Bash 和 Korn Shell 中的版本(例如)不必相同。
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
示例运行,在 Mac OS X 上使用 Bash 3.2.57:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
您不需要像使用 [ 那样引用 [[ 中的变量,因为它不像 [ 那样是一个单独的命令。
这不是一个经典的问题吗?
我会这么想的。但是,还有另一种选择,即:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
确实,如果您阅读了autoconf 工具或相关软件包的“便携式外壳”指南,他们推荐使用这种表示法——使用“||”和“&&”。我想你甚至可以做到:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
在动作与回声一样微不足道的情况下,这还不错。当要重复的动作块是多行时,重复太痛苦了,最好使用早期版本之一 - 或者您需要将动作包装到在不同 then 块中调用的函数中。