shell脚本的条件测试与比较 条件测试方法 语法1:test <测试表达式> 这是利用test命令进行条件测试表达式的方法。test命令和"<测试表达式>"之间至少有一个空格 语法2:[ <测试表达式> ] 这是通过[]进行条件测试表达式的方法。和test命令用法相同,推荐此方法。[]的边界和内容至少有一个空格 语法3:[[ <测试表达式> ] ] 这是通过[[ ]]进行条件测试表达式的方法。[[]]的边界和内容至少有一个空格 语法4: ((<测试表达式> )) 这是通过(())进行条件测试表达式的方法,一般用于if语句里。(())前端不需要空格 语法1中的test命令和语法2中的[]是等价的。语法3中的[[]]为扩展的test命令,语法4中的(())命令常用于计算,建议在生产环境中使用相对友好的语法2,即中括号[]的语法 在双中括号[[]]中可以使用通配符(如*)等进行模式匹配,这是区别于其他几种语法的地方 &&、||、>、<等操作符可以应用到[[]]中,但不能应用于[]中,在[]中一般用-a、-o、-gt、-lt取代 对于整数的关系运算,也可以使用Shell的算术运算符(()) test条件测试的语法及示例 test 条件测试的语法格式为: test <测试表达式> 在 test 命令中 使用 -f 选项(文件存在且为普通文件则表达式成立) 测试文件 [root@VM_0_15_centos ~]# test -f file && echo true || echo false false [root@VM_0_15_centos ~]# touch file [root@VM_0_15_centos ~]# test -f file && echo true || echo false true 在 test 命令中使用 -z 选项(如果测试字符串的长度为 0, 则表达式成立)测试字符串 [root@VM_0_15_centos ~]# test -z "liangguojun" && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# char="liangguojun" [root@VM_0_15_centos ~]# test -z "$char" && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# char="" [root@VM_0_15_centos ~]# test -z "$char" && echo 1 || echo 0 1 [](中括号)条件测试语法及示例 []条件测试的语法格式 为: [<测试表达式>] 利用[]加 -f 选项(文件存在且为普通文件则表达式成立)测试文件,也可以只写前一半(即只有&&部分)或者后一半(即只有||部分) [root@VM_0_15_centos ~]# [ -f /tmp/test.log ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# touch /tmp/test.log [root@VM_0_15_centos ~]# [ -f /tmp/test.log ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -f /tmp/test.log ] && echo 1 1 [root@VM_0_15_centos ~]# [ -f /tmp/test.log ] || echo 0 [root@VM_0_15_centos ~]# [ -f /tmp/test2.log ] || echo 0 0 [[]] 条件测试语法及示例 [[]] 条件测试语法格式为:[[ <测试表达式> ] ] [[]] 的使用示例 如果 /tmp/test.log 文件存在并且是普通文件,则为真,因为文件不存在,所以输出 0 [root@VM_0_15_centos ~]# [[ -f /tmp/test.log ]] || echo 0 0 [root@VM_0_15_centos ~]# touch /tmp/test.log [root@VM_0_15_centos ~]# [[ -f /tmp/test.log ]] || echo 0 [root@VM_0_15_centos ~]# rm -f /tmp/test.log [root@VM_0_15_centos ~]# [[ -f /tmp/test.log ]] || echo 0 0 文件测试表达式 常用文件测试操作符 -d 文件 文件存在且为目录为真,即测试表达试成立 -f 文件 文件存在且为普通文件则为真 -e 文件 文件存在则为真,-f,-e不辨别是目录还是文件 -r 文件 文件存在且可读则为真 -s 文件 文件存在且文件大小不为0为真 -w 文件 文件存在且可写则为真 -x 文件 文件存在且可执行则为真 -L 文件 文件存在且为链接文件则为真 f1 -nt f2 文件1比文件2新则为真 f1 -ot f2 文件1比文件2旧则为真 普通文件条件表达式测试 如果测试文件存在,则输出1,否则输出0 [root@VM_0_15_centos ~]# touch test.log [root@VM_0_15_centos ~]# ls -l test.log -rw-r--r-- 1 root root 0 Jun 4 11:07 test.log [root@VM_0_15_centos ~]# [ -f test.log ] && echo 1 || echo 0 1 普通目录条件表达式测试 下面测试中, testdir 非普通文件,因为创建的是目录,因此 -f 测试输出的是0 。testdir2 目录不存在,所以输出 0 [root@VM_0_15_centos ~]# mkdir testdir [root@VM_0_15_centos ~]# ls -lh total 4.0K drwxr-xr-x 2 root root 4.0K Jun 4 11:09 testdir [root@VM_0_15_centos ~]# [ -f testdir ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ -e testdir ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -d testdir ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -d testdir2 ] && echo 1 || echo 0 0 文件属性条件表达式测试 [root@VM_0_15_centos ~]# touch test.sh [root@VM_0_15_centos ~]# ls -l test.sh -rw-r--r-- 1 root root 0 Jun 5 10:48 test.sh [root@VM_0_15_centos ~]# [ -r test.sh ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -w test.sh ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -x test.sh ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# chmod 001 test.sh [root@VM_0_15_centos ~]# ls -lh test.sh ---------x 1 root root 0 Jun 5 10:48 test.sh [root@VM_0_15_centos ~]# [ -w test.sh ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -r test.sh ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -x test.sh ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# echo 'echo test'> test.sh [root 上面例子中,因为 root 用户特殊性,所以用户权限位没有w和r也可以写、读。 常用字符串测试操作符 -n "字符串" 若字符串的长度不为0,则为真,n可理解为no zero -z "字符串" 若字符串的长度为0,则为真 "串1"="串2" 若字符串1等于字符串2,则为真 "串1"!="串2" 若字符串1不等于字符串2,则为真 注意: "=”"两边需要有空格。"["和"]" 两边也要有空格。对于字符串的测试,一定要将字符串加双引号之后再比较。 字符串条件表达式测试实践 [root@VM_0_15_centos ~]# [ -n "abc" ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# test -n "abc" && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# test -n "abc " && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# test -n "" && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# var="hao123" [root@VM_0_15_centos ~]# [ -n "$var" ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ -n $var ] && echo 1 || echo 0 #<== 去掉引号看上去是对的,不过最好还是加上引号 1 [root@VM_0_15_centos ~]# var="baidu" [root@VM_0_15_centos ~]# [ -z "$var" ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ "abc" = "abc" ] && echo 1 || echo 0 #<== 注意 "=" 两端要有空格 1 [root@VM_0_15_centos ~]# [ "$var" = "baidu" ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ "$var" == "baidu" ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ "$var" != "baidu" ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ "$var" != "baidudududu" ] && echo 1 || echo 0 1 进行字符串比较时,等号两边没有空格和 "["或者"]"两边没有空格,会带来问题 [root@VM_0_15_centos ~]# [ "abc"="1" ] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [ "abc" = "abcd" ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ "abc"="abcd" ] && echo 1 || echo 0 #<== 等号两端没有空格,则会出现明显的问题,明明表达式不成立,却输出了1 1 [root@VM_0_15_centos ~]# ["abc" = "abcd"] && echo 1 || echo 0 #<== 等"["或者"]"两边没有空格,则语法错误 -bash: [abc: command not found 0 字符串不加引号可能带来的问题 [root@VM_0_15_centos ~]# var="" [root@VM_0_15_centos ~]# [ -n "$var" ] && echo 1 || echo 0 #<== 此命令的结果输出是正确的。 0 [root@VM_0_15_centos ~]# [ -n $var ] && echo 1 || echo 0 #<== 此命令的结果输出是错误的。同样的表达式,加引号和不加引号的结果相反的,说明加双引号的重要性。 1 [root@VM_0_15_centos ~]# [ -z "$var" ] && echo 1 || echo 0 1 整数二元比较操作符 []及test使用的比较符号 (())和[[]]使用的比较符号 说明 -eq ==或= 相等,equal -ne != 不相等,not equal -gt > 大于,greater than -ge >= 大于等于,greater equal -lt < 小于,less than -le <= 小于等于,less equal 注意: “=” 和“!=” 也可在[]中做比较使用,但在[] 中使用包含“>” 和“<” 的符号时,需要用反斜线转义,有时不转义虽然语法不会报错,但是结果可能会不对。 也可以在[[]] 中 使用 包含“- gt” 和“- lt” 的符号,但是不建议这样使用。 比较符号两端也要有空格。 二元数字在 [] 中使用 "<"、">" 非标准符号的比较 [root@VM_0_15_centos ~]# [ 2 > 1 ] && echo 1 || echo 0 #<== 正确的输出 1 [root@VM_0_15_centos ~]# [ 2 < 1 ] && echo 1 || echo 0 #<== 错误的输出。可见 "<"操作符带来问题 1 [root@VM_0_15_centos ~]# [ 2 < 1 ] && echo 1 || echo 0 #<==正确的输出 0 [root@VM_0_15_centos ~]# [ 2 = 1 ] && echo 1 || echo 0 #<==正确的输出 0 [root@VM_0_15_centos ~]# [ 2 = 2 ] && echo 1 || echo 0 #<==正确的输出 1 [root@VM_0_15_centos ~]# [ 2 != 2 ] && echo 1 || echo 0 #<==正确的输出 0 二元数字在[] 中使用 -gt、-le类符号的比较 [root@VM_0_15_centos ~]# [ 2 -gt 1 ] && echo 1 || echo 0 #<==正确的输出 1 [root@VM_0_15_centos ~]# [ 2 -ge 1 ] && echo 1 || echo 0 #<==正确的输出 1 [root@VM_0_15_centos ~]# [ 2 -le 1 ] && echo 1 || echo 0 #<==正确的输出 0 [root@VM_0_15_centos ~]# [ 2 -lt 1 ] && echo 1 || echo 0 #<==正确的输出 0 二元数字配合不同种类的操作符在[[]]中的比较 [root@VM_0_15_centos ~]# [[ 5 > 6 ]] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [[ 5 < 6 ]] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [[ 5 != 6 ]] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# [[ 5 = 6 ]] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [[ 5 -gt 6 ]] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [[ 5 -lt 6 ]] && echo 1 || echo 0 1 二元数字在(())中的比较 [root@VM_0_15_centos ~]# (( 3> 2 )) && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# (( 3 > 2 )) && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# (( 3 < 2 )) && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# (( 3 == 2 )) && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# (( 3 !== 2 )) && echo 1 || echo 0 -bash: ((: 3 !== 2 : syntax error: operand expected (error token is "= 2 ") 0 [root@VM_0_15_centos ~]# (( 3 != 2 )) && echo 1 || echo 0 1 通过[]实现整数条件测试 有关整数(确定是整数,否则会报错)大小比较,推荐使用本例子的方法,不推荐 (()) 和 [[]] [root@VM_0_15_centos ~]# a1=98;a2=99 [root@VM_0_15_centos ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ $a1 -gt $a2 ] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [ $a1 -lt $a2 ] && echo 1 || echo 0 1 利用 [[]] 和(())实现直接通过常规数学运算符进行比较 [root@VM_0_15_centos ~]# a1=98;a2=99 [root@VM_0_15_centos ~]# [[ $a1 > $a2 ]] && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# [[ $a1 < $a2 ]] && echo 1 || echo 0 1 [root@VM_0_15_centos ~]# (( $a1 >= $a2 )) && echo 1 || echo 0 0 [root@VM_0_15_centos ~]# (( $a1 <= $a2 )) && echo 1 || echo 0 1 有关[]、[[]]、(()) 用法的小结: 整数加双引号的比较是对的。 [[]]中用类似 -eq 等的写法是对的,[[]] 中用类似>、< 的写法也可能不对,有可能会只比 第一位,逻辑结果不对。 []中用 类似>、< 的写法在语法上虽然可能没错, 但逻辑结果不对,可以使用=、!= 正确比较。 (()) 中不能使用类似 -eq 等的写法,可以使用类似>、< 的写法。 逻辑操作符 []及test使用的比较符号 (())和[[]]使用的比较符号 说明 -a && and,与,两端都为真,结果为真 -o || or,或,两端有一个为真,结果为真 ! ! not,非,两端相反,结果为真 说明: 逻辑 操作符前后的表达式是否成立, 一般用真假来表示。 “!” 的中文意思是反,即与一个逻辑值相反的逻辑值。 -a 的中文意思是“与”( and 或&&),前后两个逻辑值都为“真”,综合返回值才为“真”,反之为“假”。 -o 的中文意思是“或”( or 或||),前后两个逻辑值只要有一个为“真”,返回值 就为“真”。 连接两含[]、 test或[[]] 的表达式可用&& 或||。