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或[[]] 的表达式可用&& 或||。
![]()