六、Shell脚本的条件测试

一、条件测试语法

语法1:test <测试表达式>
利用test命令进行条件测试表达式的方法。test命令与<测试表达式>之间至少有一个空格。

语法2:[ <测试表达式> ]
通过[](单中括号)进行条件测试表达式的方法,和test命令用法相同。[]的边界和内容之间至少有一个空格。

语法3:[[ <测试表达式> ]]
通过[[]](双中括号)进行条件测试表达式的方法,比test和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格。

语法4:((<测试表达式>))
通过(())(双小括号)进行条件测试表达式的方法,一般用于if语句。(())(双小括号)两端不需要有空格。
注意:
1)、语法1中的test命令和语法2中的[]是等价的。语法3中的[[]]为扩展的test命令,语法4中的(())常用于计算,:建议使用相对友好的语法2,即中括号([])的语法格式。
2)、在[[]](双中括号)中可以使用通配符等进行模式匹配,这是其区别于其他几种语法格式的地方。
3)、&&、||、>、<等操作符可以应用于[[]]中,但不能应用于[]中,在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数)代替上述操作符。
4)、对于整数的关系运算,也可以使用Shell的算术运算符(())

1、test条件测试的简单语法及示例

test条件测试的语法格式为:test<测试表达式> 对于如下语句: test -f file && echo true || echo false

该语句表示如果file文件存在,则输出true,否则(||)输出false。这里的&&是并且的意思。test的-f参数用于测试文件是否为普通文件,test命令若执行成功(为真),则执行&&后面的命令,而||后面的命令是test命令执行失败之后(为假)所执行的命令。 test命令测试表达式的逻辑也可以用上述表达形式的一半逻辑(即仅有一个&&或||)来测试,示例如下。

test -f /tmp/test.txt && echo 1 #<==若表达式成功,则输出1。 test -f /tmp/test.txt || echo 0 #<==若表达式不成功,则输出0。

提示:关于test测试表达式的更多知识可执行man test查看帮助,大部分场景都会使用[]的语法替代test命令的语法。

案例

在test命令中使用-f选项(文件存在且为普通文件则表达式成立)测试文件。

判断/tmp是否存在一个ywx的文件,存在则打印true,不存在则打印false
[root@node1 ~]# test -f /tmp/ywx && echo true || echo false
false   #ywx文件不存在,打印false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# test -f /tmp/ywx && echo true || echo false
true    #ywx文件存在,打印true

在test命令中使用-z选项(如果测试字符串的长度为0,则表达式成立)测试字符串。

判断king的字符长度是否为0,为0则打印1,不为0则打印0
[root@node1 ~]# test -z "king" && echo 1 || echo 0
0
#king的字符串长度不为0,打印结果为0

判断是否给一个变量SEAL赋值,赋值则打印结果为0,没有赋值则打印结果为1
[root@node1 ~]# echo $SEAL

[root@node1 ~]# test -z "$SEAL" && echo 1|| echo 0
1
#SEAL变量没有被赋值,结果显示为1
[root@node1 ~]# SEAL=ywx
[root@node1 ~]# echo $SEAL
ywx
[root@node1 ~]# test -z "$SEAL" && echo 1|| echo 0
0
#SEAL的赋值为ywx,打印结果为0

2、[](中括号)条件测试语法及示例

[]条件测试的语法格式为:[ <测试表达式> ],注意[]两边有空格

-f /tmp/ywx.txt ] && echo 1 || echo 0

如果/tmp/ywx.txt文件存在,则输出1,否则(||)输出0。这里的&&表示并且。[]的应用同test命令,若中括号里的命令执行成功(返回真),则执行&&后面的命令,否则执行||后面的命令。 []测试表达式的逻辑也可以用如下的语法来判断逻辑的表达式写法(test命令的用法也适合于此),即: [ -f /tmp/ywx.txt ] && echo 1 #<==若表达式成功,则输出1。 [ -f /tmp/ywx.txt ] || echo 0 #<==若表达式不成功,则输出0

提示:[]命令的选项和test命令的选项是通用的,因此,使用[]时的参数选项可以通过man test命令获得帮助。

案例

在[]使用-f选项(文件存在且为普通文件则表达式成立)测试文件。

判断/tmp是否存在一个ywx的文件,存在则打印true,不存在则打印false
[root@node1 ~]# [ -f /tmp/ywx ]&& echo true|| echo false
false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# [ -f /tmp/ywx ]&& echo true|| echo false
true

3、[[]]条件测试语法及示例

[[]]条件测试的语法格式为:[[ <测试表达式> ]]。注意[[]]两边有空格

[[ -f /tmp/ywx.txt ]] && echo 1 || echo 0

如果/tmp/ywx.txt文件存在就输出1,否则(||)就输出0。这里的&&表示并且。[[]]的应用属于[]和test命令的扩展命令,功能更丰富也更复杂。如果双中括号里的表达式成立(为真),则执行&&后面的命令,否则执行||后面的命令。 [[]]测试表达式的逻辑也可以使用如下的部分逻辑形式,即: [[ -f /tmp/ywx.txt ]] && echo 1 #<==若表达式成功则输出1。 [[ -f /tmp/ywx.txt ]] || echo 0 #<==若表达式不成功则输出0。

另外,逻辑操作符&&和||的两端可以有空格也可以无空格。

双中括号内部的两端要有空格,[[]]里的测试判断选项,也可以通过man test来获得,[[]]表达式与[]和test用法的选项部分是相同的,其与[]和test测试表达式的区别在于,在[[]]中可以使用通配符等进行模式匹配;并且&&、||、>、<等操作符可以应用于[[]]中,但不能应用于[]中,在[]中一般使用-a、-o、-gt(用于整数)、-lt(用于整数)等操作符代替上文提到的用于[[]]中的符号。除了使用通配符功能之外,建议放弃这个双中括号的写法,虽然它是较新的test命令的语法格式。

案例

在[[]]使用-f选项(文件存在且为普通文件则表达式成立)测试文件。

判断/tmp是否存在一个ywx的文件,存在则打印true,不存在则打印false
[root@node1 ~]# [[ -f /tmp/ywx ]]&& echo true|| echo false
false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# [[ -f /tmp/ywx ]]&& echo true|| echo false
true

二、文件测试表达式

-d(directory)目录
文件存在且为目录则位真,及测试表达式成立

-f(file)文件
文件存在且为普通文件则位真,及测试表达式成立

-e(exist)
文件存在则为真,及测试表达式成立。不区分文件或目录。

-r(read)文件
文件存在且有可读权限则为真,及测试表达式成立

-s(size)文件
文件存在且文件小大不为0则为真,及测试表达式成立

-w(write)文件
文件存在且有可写权限则为真,及测试表达式成立

-x(executable)文件
文件存在且有可执行权限则为真,及测试表达式成立

-L(link)文件
文件存在且为链接文件则为真,及测试表达式成立

f1 -nt f2, nt(newer than)
文件f1比文件f2新则为真,及测试表达式成立。根据文件的修改时间来计算

f1 -ot f2, ot(older than)
文件f1比文件f2旧则为真,及测试表达式成立。根据文件的修改时间来计算

1、普通文件测试表达式示例

[root@node1 ~]# [ -f /etc/hosts ]&&echo 1|| echo 0
1
#文件存在则为1,不存在则为0

2、目录文件(测试文件类型)

[root@node1 ~]# [ -f /etc ]&&echo 1|| echo 0
0   #不存在/etc的普通文件
[root@node1 ~]# [ -d /etc ]&&echo 1|| echo 0
1   #/etc存在且为目录
[root@node1 ~]# [ -e /etc ]&&echo 1|| echo 0
1  #/etc存在就行,不管是目录还是文件
#/etc目录存在为1,不存在为0

3、测试文件属性示例

[root@node1 ~]# ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[root@node1 ~]# [ -r /etc/hosts ]&& echo 1|| echo 0
1   #有r权限
[root@node1 ~]# [ -w /etc/hosts ]&& echo 1|| echo 0
1   #有w权限
[root@node1 ~]# [ -x /etc/hosts ]&& echo 1|| echo 0
0   #无x权限

[root@node1 ~]# su - ywx
Last login: Sun Oct  4 03:32:51 CST 2020 on pts/0
ni hao shell
[ywx@node1 ~]$ ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[ywx@node1 ~]$ [ -r /etc/hosts ]&&echo 1||echo 0
1
[ywx@node1 ~]$ [ -w /etc/hosts ]&&echo 1||echo 0
0
[ywx@node1 ~]$ [ -x /etc/hosts ]&&echo 1||echo 0
0

测试文件的读、写、执行等属性,不光是根据文件属性rwx的标识来判断,还要看当前执行测试的用户是否真的可以按照对应的权限操作该文件。

4、测试文件大小是否为0

[root@node1 ~]# ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[root@node1 ~]# ll /tmp/ywx
-rw-r--r-- 1 root root 0 Oct  5 22:46 /tmp/ywx

[root@node1 ~]# [ -s /etc/hosts ]&&echo 1||echo 0
1
[root@node1 ~]# [ -s /etc/ywx ]&&echo 1||echo 0
0

5、测试shell变量

[root@node1 ~]# file1="/etc"
[root@node1 ~]# echo $file1
/etc
[root@node1 ~]# [ -f "$file1" ]&&echo 1||echo 0
0   #变量$file1不为文件
[root@node1 ~]# [ -d "$file1" ]&&echo 1||echo 0
1   #变量$file1是目录
[root@node1 ~]# [ -s "$file1" ]&&echo 1||echo 0
1    #变量$file1大小不0
[root@node1 ~]# [ -e "$file1" ]&&echo 1||echo 0
1    #变量$file1存在

注意:用[]测试变量时,如果被测试的变量不加双引号,那么测试结果可能会是不正确的

 
[root@node1 ~]# unset KAKA
[root@node1 ~]# echo $KAKA   #变量KAKA没有赋值

[root@node1 ~]# [ -f $KAKA ]&& echo 1||echo 0
1
[root@node1 ~]# [ -f "$KAKA" ]&& echo 1||echo 0
0
#对变量而言不加"",当该变量没有赋值时结果不正确的

6、特殊条件测试表达式案例

以下写法适用于所有的条件测试表达式,是工作中比较常用的替代if语句的方法。判断条件测试表达式的条件成立或不成立后,还需要继续执行多条命令语句的语法形式如下:

[ 条件1 ] &&{ 命令1 命令2 命令3 }

上面的判断相当于下面if语句的效果。

if [ 条件1 ] then

命令1

命令2

命令3

fi

如果/etc存在且为目录时则同时打印etc is exist和 etc is directory
[root@node1 ~]# [ -d /etc ] && { echo "etc is exist";echo "etc is directory"; }||echo "etc not exist"
etc is exist
etc is directory
#注意{}两边要有空格,每条命令以";"结尾

三、字符串测试表达式

1、操作符

字符串测试操作符的作用包括:比较两个字符串是否相同、测试字符串的长度是否为零、字符串是否为NULL等

-n "字符串"
若字符串长度不为0,则为真,及测试表达式成立,n(no zero)

-z "字符串"
若字符串长度为0,则为真,及测试表达式成立,z(zero)

"字符串1" = "字符串2"
若字符串1等于字符串2,则为真,及测试表达式成立,也可以使用"=="

"字符串1" != "字符串2"
若字符串1不等于字符串2,则为真,及测试表达式成立,不能使用!==

·对于字符串的测试,一定要将字符串加双引号之后再进行比较。如[ -n "$myvar" ],特别是使用[]的场景。
·比较符号(例如=和!=)的两端一定要有空格。
·“!=”和“=”可用于比较两个字符串是否相同。

2、案例

[root@node1 ~]# [ -n "abc" ] && echo 1 || echo 0  #<==如果字符串长度不为0,则输出1,否则输出0。
1 #<==因为字符串为abc,长度不为0,因此为真,输出1。
[root@node1 ~]# test -n "abc" && echo 1 || echo 0 #<==test的用法同上述[]的用法。1
[root@node1 ~]# test -n "" && echo 1 || echo 0
0
[root@node1 ~]# var="ywx1" #<==给变量var赋值ywx1字符串。
[root@node1 ~]# [ -n "$var" ] && echo 1 || echo 0   #<==如果字符串长度不为0,
                                                           则输出1,否则输出0。
1 #<==因为变量var内容字符串为ywx1,长度不为0,因此为真,输出1。
[root@node1 ~]# [ -n $var ] && echo 1 || echo 0 #<==去掉双引号在这里看起来也是对的,不过还是加上为好。
1
[root@node1 ~]# var="ywx1"
[root@node1 ~]# [ -z "$var" ] && echo 1 || echo 0  #<==使用-z,变量长度为0,则为真。
0   #<==变量var的值为ywx1,长度不为0,所以表达式不成立,输出0。
[root@node1 ~]# [ "abc" = "abc" ] && echo 1 || echo 0
#<==字符串相等,输出1,注意“=”两端要有空格。
1
[root@node1 ~]# [ "abc" = "abd" ] && echo 1 || echo 0#<==字符串不相等,输出0,注意“=”两端要有空格。
0
[root@node1 ~]# [ "$var" = "ywx1" ] && echo 1 || echo 0
#<==变量值和字符串相等,输出1。
1
[root@node1 ~]# [ "$var" == "ywx1" ] && echo 1 || echo 0
#<==使用“==”代替“=”,注意“=”两端要有空格。
1
[root@node1 ~]# [  "$var"!= "ywx1" ] && echo 1 || echo 0
0

进行字符串比较时,等号两端没有空格带来的问题

[root@node1 ~]# ["abc"="1"] && echo 1||echo 0  #<==若等号两端不带空格,则会出现明显的逻辑错误。
1  #<==明明表达式不成立,却输出了1。
[root@node1 ~]# [ "abc" = "1" ] && echo 1||echo 0 #<==带空格的就是准确的。
0  #<==表达式不成立,输出0
#字符串比较时若等号两端没有空格,则会导致判断出现逻辑错误,即使语法没问题,但是结果依然可能不对。

字符串不加引号可能带来的问题。

[root@node1 ~]# var="" #<==将变量内容置为空。
[root@node1 ~]# [ -n "$var" ] && echo 1 || echo 0  #<==有双引号。
0 #<==给变量加双引号,返回0,-n不为空时为真,因为变量内容为空,因此输出0是对的。
[root@node1 ~]# [ -n $var ] && echo 1 || echo 0     #<==去掉双引号。
1 #<==同样的表达式,不加引号和加双引号后测试的结果相反,可见加双引号的重要性。
[root@node1 ~]# [ -z "$var" ] && echo 1 || echo 0 #<==如果字符串长度为0,则输出1,否则输出0。
1
#字符串不加双引号,可能会导致判断上出现逻辑错误,即使语法没问题,但是结果依然可能不对。

四、整数二元比较操作符

1、整数二元比较操作符

在[]和test中使用的比较符

-eq:相等
-ne: 不等于
-gt: 大于
-ge: 大于等于
-lt: 小于
-le:小于等于

在(())和[[]]中使用的比较符号

 
==或==
>
>=
<
<=
1)·“=”和“!=”也可在[]中做比较使用,但在[]中使用包含“>”和“<”的符号时,需要用反斜线转义,有时不转义虽然语法不会报错,但是结果可能会不对。
2)·也可以在[[]]中使用包含“-gt”和“-lt”的符号,但是不建议这样使用。
3)·比较符号两端也要有空格。

2、案例

二元数字在[]中使用“<”、“>”非标准符号的比较。

[root@node1 ~]# [ 2 > 1 ] && echo 1 || echo 0
1
[root@node1 ~]# [ 2 < 1 ] && echo 1 || echo 0
1  #<==这里的结果逻辑不对,条件不成立,则应该返回0,可见,“<”操作符在[]里使用时会带来问题。
[root@node1 ~]# [ 2 \< 1 ] && echo 1 || echo 0
0 #<==转义后这里是正确的。
[root@node1 ~]# [ 2 = 1 ] && echo 1 || echo 0   #<==比较相等符号是正确的。
0
[root@node1 ~]# [ 2 = 2 ] && echo 1 || echo 0   #<==比较相等符号是正确的。
1
[root@node1 ~]# [ 2!= 2 ] && echo 1 || echo 0  #<==比较不相等符号也是正确的。
0

二元数字在[]中使用-gt、-le类符号的比较。

[root@node1 ~]# [ 2 -gt 1 ] && echo 1 || echo 0
1  #<==2大于1成立,输出1。
[root@node1 ~]# [ 2 -ge 1 ] && echo 1 || echo 0
1  #<==2大于等于1成立,输出1。
[root@node1 ~]# [ 2 -le 1 ] && echo 1 || echo 0
0  #<==2小于等于1不成立,输出0。
[root@node1 ~]# [ 2 -lt 1 ] && echo 1 || echo 0
0  #<==2小于1不成立,输出0。

二元数字配合不同种类的操作符在[[]]中的比较。

[root@node1 ~]# [[ 5 > 6 ]] && echo 1 || echo 0
0  #<==5大于6不成立,输出0。
[root@node1 ~]# [[ 5 < 6 ]] && echo 1 || echo 0
1  #<==5小于6成立,输出1。
[root@node1 ~]# [[ 5!= 6 ]] && echo 1 || echo 0
1  #<==5不等于6成立,输出1。
[root@node1 ~]# [[ 5 = 6 ]] && echo 1 || echo 0
0  #<==5等于6不成立,输出0。
[root@node1 ~]# [[ 5 -gt 6 ]] && echo 1 || echo 0
0  #<==5大于6不成立,输出0。
[root@node1 ~]# [[ 5 -lt 6 ]] && echo 1 || echo 0
1  #<==5小于6成立,输出1。
[root@node1 ~]# [[ 65 > 66 ]] && echo 1 || echo 0
0  #<==65大于66不成立,输出0。
[root@node1 ~]# [[ 65 < 66 ]] && echo 1 || echo 0
1  #<==65小于66成立,输出1。
[root@node1 ~]# [[ 65 = 66 ]] && echo 1 || echo 0
0  #<==65等于66不成立,输出0。

二元数字在(())中的比较。

[root@node1 ~]# ((3>2)) && echo 1 || echo 0
1  #<==3大于2成立,输出1。
[root@node1 ~]# ((3<2)) && echo 1 || echo 0
0  #<==3小于2不成立,输出0。
[root@node1 ~]# ((3==2)) && echo 1 || echo 0
0  #<==3等于2不成立,输出0。
[root@node1 ~]# ((3!==2)) && echo 1 || echo 0 #<==“!==”符号不可用,语法错误
bash:((:3!==2:syntax error:operand expected (error token is "=2")
0
[root@node1 ~]# ((3!=2))&& echo 1 || echo 0
1

有关[]、[[]]、(())用法的小结:

 
1)·整数加双引号的比较是对的。
2)·[[]]中用类似-eq等的写法是对的,[[]]中用类似>、<的写法也可能不对,有可能会只比较第一位,逻辑结果不对。
3)·[]中用类似>、<的写法在语法上虽然可能没错,但逻辑结果不对,可以使用=、!=正确比较。
4)·(())中不能使用类似-eq等的写法,可以使用类似>、<的写法。

整数变量测试实践示例

通过[]实现整数条件测试。

[root@node1 ~]# a1=98;a2=99
[root@node1 ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0 #<==测试$a1是否等于$a2
0
[root@node1 ~]# [ $a1 -gt $a2 ] && echo 1 || echo 0 #<==测试$a1是否大于$a2。
0
[root@node1 ~]# [ $a1 -lt $a2 ] && echo 1 || echo 0 #<==测试$a1是否小于$a2。
1

利用[[]]和(())实现直接通过常规数学运算符进行比较。

 
[root@node1 ~]# [[ $a1 > $a2 ]] && echo 1 || echo 0  #<==测试$a1是否大于$a2,尽量不用此写法。
0
[root@node1 ~]# [[ $a1 < $a2 ]] && echo 1 || echo 0  #<==测试$a1是否小于$a2,尽量不用此写法。
1
[root@node1 ~]# (( $a1 >= $a2 )) && echo 1 || echo 0   #<==测试$a1是否大于等于$a2,此写法也可以。
0
[root@node1 ~]# (( $a1 <= $a2 )) && echo 1 || echo 0   #<==测试$a1是否小于等于$a2,
1

有关整数(要确认是整数,否则会报错)的大小比较,(())语法要优于[[]],但还是推荐优先使用[],次选是(()),不推荐使用[[]]。示例如下:

 
[ num1 –eq num2 ]     #<==注意比较符号两边的空格和比较符号的写法,必须要有空格。
(( num1 > num2 ))         #<==比较符号两边无需空格(多空格也可),使用常规数学的比较符号即可。

五、逻辑操作符

1、逻辑操作符

在[]和test中使用

-a and,与,两端都为真,则结果为真
-o or,或,两端有一个为真,则结果为真
!  not,非,两端取反,则结果为真

在[[]]和(())中使用

&& and,与,两端都为真,则结果为真
|| or,或,两端有一个为真,则结果为真
!   not,非,两端取反,则结果为真
1)·逻辑操作符前后的表达式是否成立,一般用真假来表示。
2)·“!”的中文意思是反,即与一个逻辑值相反的逻辑值。
3)·-a的中文意思是“与”(and或&&),前后两个逻辑值都为“真”,综合返回值才为“真”,反之为“假”。
4)·-o的中文意思是“或”(or或||),前后两个逻辑值只要有一个为“真”,返回值就为“真”。
5)·连接两含[]、test或[[]]的表达式可用&&或||。

2、逻辑操作符运算规则

-a和&&的运算规则:只有逻辑操作符两端的表达式都成立时才为真;真(true)表示成立,对应的数字为1;假(false)表示不成立,对应的数字为0

[root@node1 ~]# [ -f /etc/hosts -a -f /etc/services ] && echo 1 || echo 0
#<==单中括号文件测试。
1
[root@node1 ~]# [[ -f /etc/hosts && -f /etc/services ]] && echo 1 || echo 0
#<==双中括号文件测试。
1
使用-a和&&的综合表达式结果,相当于将两端表达式结果的对应数字(0或1)相乘。
当左边为真,右边为假的时候,相乘结果为1*0=0,总结果为假(0)。
当左边为假,右边为真的时候,相乘结果为0*1=0,总结果依然为假(0)。
当左边为真,右边也为真的时候,相乘结果为1*1=1,总结果为真(1)。
当左边为假,右边也为假的时候,相乘结果为0*0=0,总结果为假(0)。
简单表示为:
and结果1*0=0 假
and结果0*1=0 假
and结果1*1=1 真
and结果0*0=0 假
结论:and(&&)也称为与,只有两端都是1时才为真,相当于取前后表达式的交集。

-o或||两端都是0才为假,任何一端不为0就是真,这相当于将两边表达式结果的对应数字(0或1)相加,对应的表达式为:

[root@node1 ~]# [ 5 -eq 6 -o 5 -gt 3 ] && echo 1 || echo 0
1
[root@node1 ~]# ((5==6||5>3)) && echo 1 || echo 0
1
-o或||的运算规则为:
当左边为真,右边为假的时候,相加结果为1+0=1,总结果为真(1)。
当左边为假,右边为真的时候,相加结果为0+1=1,总结果依然为真(1)。
当左边为真,右边也为真的时候,相加结果为1+1=2,总结果为真(1),非0即真。
当左边为假,右边也为假的时候,相加结果为0+0=0,总结果为假(0)。
简单表示为:
or 结果1+0=1 真
or 结果1+1=2 真(非0即为真)
or 结果0+1=1 真
or 结果0+0=0 假
结论:or(||)也称为或,它的两端表达式的结果都是0时才为假,不为0就是真。相当于对前后表达式结果取并集。

案例

[]里的逻辑操作符配合文件测试表达式使用的示例。

[root@node1 ~]# f1=/etc/rc.local;f2=/etc/services
#<==定义f1和f2两个变量,分别赋值两个已知存在的文件路径。
[root@node1 ~]# echo -ne "$f1 $f2\n"  #<==测试输出f1和f2两个变量的值。
/etc/rc.local /etc/services
[root@node1 ~]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0 #<==[]里使用-a(and)。
#<==测试f1和f2两个变量值是否都为普通文件,如果成立,则输出1,否则输出0。
1
[root@node1 ~]# [ -f "$f1" -o -f "$f222" ] && echo 1 || echo 0
#<==测试f1和f222两个变量值是否都为普通文件,如果成立,则输出1,否则输出0;f222变量是未定义的,但是f1变量是有的,并且是普通文件,-o两边有一个表达式成立(即为真),因此输出1。
1
[root@node1 ~]# [ -f "$f111" -o -f "$f222" ] && echo 1 || echo 0
#<==测试f111和f222两个变量值中是否有一个为普通文件,如果成立,则输出1,否则输出0。
0 #<==f111和f222两个变量都是未定义的,因此输出0。
[root@node1 ~]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0 #<==这是错误语法,[]中不能用&&或||-bash:[:missing `]'
0
[root@node1 ~]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0
#<==如果在[]中想使用&&,则这样用。
1

[[]]里逻辑操作符配合字符串的条件表达式的测试示例。

[root@node1 ~]# a="ywx";b="kaka"  #<==定义a和b两个变量,赋值两个已知的字符串。
[root@node1 ~]# echo -ne "$a $b\n"  #<==测试输出a和b两个变量的值。
ywx kaka
[root@node1 ~]# [[!-n "$a" && "$a" = "$b" ]] && echo 1 || echo 0
#<== [[]]内部用&&或||。
#<==测试$a长度不为0是否成立,并且$a等于$b是否成立,两个表达式是否同时成立。
0 #<==因为$a长度不为0成立,结果为1,加上前面“!”取反,就是不成立,结果变为0。$a等于$b成立,结果为1,两个表达式综合起来0*1=0,因此不成立,输出0。
[root@node1 ~]# [[ -z "$a" || "$a"!= "$b" ]] && echo 1 || echo 0
#<== [[]]中||的使用。
1
[root@node1 ~]# [[ -z "$a" -o "$a"!= "$b" ]] && echo 1 || echo 0
#<== [[]]内部用-a或-o会报错。
-bash:syntax error in conditional expression
-bash:syntax error near `-o'

(())里逻辑操作符配合整数的条件表达式测试示例。

[root@node1 ~]# m=21;n=38
[root@node1 ~]# ((m>20&&n>30)) && echo 1 || echo 0 #<== (())内部用&&或||1
[root@node1 ~]# ((m<20||n>30)) && echo 1 || echo 0
1
[root@node1 ~]# ((m<20||n<30)) && echo 1 || echo 0
0
[root@node1 ~]# ((m<20 -a n<30)) && echo 1 || echo 0
#<== (())内部用-a或-o也会报语法错误。
-bash:((:m<20 -a n<30:syntax error in expression (error token is "n<30")
0

使用多个[]号,并通过与或非进行混合测试。

[root@node1 ~]# m=21;n=38
[root@node1 ~]# [ $m -gt 20 -a $n -lt 30 ] && echo 1 || echo 0
0
[root@node1 ~]# [ $m -gt 20 ]||[ $n -lt 30 ] && echo 1 || echo 0
#<==多个[]号之间用&&或||连接。
1

总结

1)·“-a”和“-o”逻辑操作符号需要用于[]中。
2)·“&&”和“||”逻辑操作符号可用于[[]]或(())中,也可以在外部连接多个[]。
3)·注意,在[]和[[]]的两端及比较符号的两端,必须要有空格,但是对于(())不需要。

逻辑操作符企业案例

输入或通过命令行传入一个字符或数字,如果传入的数字等于1,就打印1;如果等于2,就打印2;如果不等于1也不能于2,就提示输入不对,然后退出程序。

参考答案1:使用read读入内容方案。

 
#!/bin/sh
echo -n "pls input a char:" #<==打印提示字符串,-n表示不换行。
read var #<==读取用户的输入并赋值给var变量。
[ "$var" == "1" ] &&{ #<==条件表达式判断,看变量是否等于1,注意普通字符比较多地用字符串比较的语法,即加双引号比较,而不是使用整数比较的语法,整数比较容易出错,除非确定是整数。
    echo 1
    exit 0 #<==每个逻辑正确,则以返回值0退出脚本,从而避免执行脚本后面无用的代码。
}
[ "$var" == "2" ] &&{ #<==条件表达式判断,看变量是否等于2。
    echo 2
    exit 0
}
[ "$var"!= "2" -a "$var"!= "1" ] &&{  #<==条件表达式加逻辑操作符判断,看变量是否不等于2,并且不等于1,如果都成立,则执行命令。
    echo error
    exit 0
}

参考答案2:使用脚本命令行传参读入内容的解决方案。

#!/bin/sh
var=$1 #<==将上文的read读入信息,改为脚本传参,接收脚本的第一个参数$1赋值给var。
[ "$var" == "1" ] &&{
    echo 1
    exit 0
}
[ "$var" == "2" ] &&{
    echo 2
    exit 0
}
[ "$var"!= "2" -a "$var"!= "1" ] &&{
    echo error
    exit 0
}

开发Shell脚本,分别实现以脚本传参和read读入的方式比较两个整数的大小。用条件表达式(禁止用if)进行判断并以屏幕输出的方式提醒用户比较的结果。注意:一共是开发两个脚本。在用脚本传参和read读入的方式实现时,需要对变量是否为数字及传参个数是否正确给予提示。

参考答案1:采用read方法。

#!/bin/sh
read -p "Pls input two num:" a b  #<==请求用户输入两个参数,读入后分别赋值给变量a和b。
#no1
[ -z "$a" ]||[ -z "$b" ] &&{  #<==如果$a变量长度为0或$b变量长度为0,即任何一个
                                      变量为空,则执行命令。
    echo "Pls input two num again." #<==a或b没值,表示用户输入错误,给出提示。
    exit 1 #<==以返回值1退出脚本。
}
#no2
expr $a + 10 &>/dev/null #<==判断$a是否为整数,不输出任何信息。前文已讲解过了expr
判断整数的方式。
RETVAL1=$? #<==将返回值赋值给RETVAL1,后面会用这个返回值做判断。
expr $b + 10 &>/dev/null #<==判断$b是否为整数,不输出任何信息。
RETVAL2=$? #<==将返回值赋值给RETVAL2,后面会用这个返回值做判断。
test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0||{ #<==利用test进行返回值是否为0的判断。如果有一个返回值不为0,则说明有一个变量不为整数,不合要求,打印提示后退出。
    echo "Pls input two "num" again."
    exit 2
}
#no3
[ $a -lt $b ] &&{  #<==整数比较,$a是否小于$b。
    echo "$a < $b"
    exit 0
}
#no4
[ $a -eq $b ] &&{  #<==整数比较,$a是否等于$b。
    echo "$a = $b"
    exit 0
}
#no5
[ $a -gt $b ] &&{  #<==整数比较,$a是否大于$b。
    echo "$a > $b"
}

参考答案2:通过命令行传参的方法实现。

#!/bin/sh
a=$1 #<==将上文的read读入信息改为脚本传参,接收脚本的第一个参数$1赋值给a。
b=$2 #<==将上文的read读入信息改为脚本传参,接收脚本的第二个参数$2赋值给b。
#no1
[ $# -ne 2 ] &&{ #<==传参专用判断手法,判断传参个数是否为两个。
    echo "USAGE:$0 NUM1 NUM2" #<==传参不合要求,给出用法提示。
    exit 1 #<==以返回值1退出脚本。
}
#no2
expr $a + 10 &>/dev/null    #<==整数判断,前文已讲。
RETVAL1=$?
expr $b + 10 &>/dev/null    #<==整数判断,前文已讲。
RETVAL2=$?
test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0||{
    echo "Pls input two "num" again."
    exit 2
}
#no3
[ $a -lt $b ] &&{
    echo "$a < $b"
    exit 0
}
#no4
[ $a -eq $b ] &&{
    echo "$a = $b"
    exit 0
}
#no5
[ $a -gt $b ] &&{
    echo "$a > $b"
}

六、测试表达式test、[]、[[]]、(())的区别总结

posted @ 2020-10-05 17:48  yaowx  阅读(499)  评论(0编辑  收藏  举报