在可移植的(POSIX或Bourne)shell中,可以使用多个test(或[)命令来实现表达式的分组:
# Bourne shellif commandA && commandB || commandC; then...# 或者使用test(1)命令:if [ testA ] && [ testB ] || [ testC ]; then...在上述代码中,&&和||是shell命令之间的运算符,它们具有相同的优先级,因此会从左到右进行求值。
如果需要明确指定分组,可以使用花括号:
# Bourne shellif commandA && { commandB || commandC; }; then...不推荐使用test命令的-a或-o选项,因为其结果是不确定的。
对于Bash、zsh和KornShell等shell,存在更强大的比较命令,并且使用更简单的语法:
ArithmeticExpression用于数值比较,NewTestCommand用于字符串(和文件)比较。以下是示例:
# Bash/ksh/zshif (( (n>0 && n<10) || n == -1 )); then echo "0 < $n < 10, or n==-1"fi或者
# Bash/ksh/zshif [[ ( -f $localconfig && -f $globalconfig ) || -n $noconfig ]]; then echo "configuration ok (or not used)"fi需要注意的是,在((...))和[[...]]中,&&运算符的优先级高于||运算符(类似于['s -a比-o优先级高),与shell中的&&和||运算符相反。因此,例如:
[ a = a ] || [ b = c ] && [ c = d ]会返回false,因为它相当于:
{ [ a = a ] || [ b = c ]; } && [ c = d ]表达式按从左到右的顺序求值,并且没有明确的优先级。而以下表达式:
[[ a = a || b = c && c = d ]]会返回true,因为它相当于:
[[ a = a || ( b = c && c = d ) ]]其中,&&的优先级高于||。
需要注意的是,在数字比较和字符串比较之间存在严格的区别。考虑以下示例:
n=3if [[ $n > 0 && $n < 10 ]];then echo "$n is between 0 and 10"else echo "ERROR: invalid number: $n"fi输出将是"ERROR: ....",因为在字符串比较中,"3"大于"10",因为"3"排在"1"后面,而下一个字符"0"不被考虑。如果将方括号改为双括号(( )),则可以得到预期的结果。
更多如果您觉得文章内容对你有一点帮助可以关注我,我在头条平台会持续分享更多实用的shell技巧和最佳实践,如果想系统的快速学习shell的各种高阶用法和生产环境避坑指南可以看看《shell脚本编程最佳实践》专栏,专栏里有更多的实用小技巧和脚本代码分享。