六、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的算术运算符(())
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
判断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
[]条件测试的语法格式为:[ <测试表达式> ],注意[]两边有空格
-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
[[]]条件测试的语法格式为:[[ <测试表达式> ]]。注意[[]]两边有空格
[[ -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旧则为真,及测试表达式成立。根据文件的修改时间来计算
[root@node1 ~]# [ -f /etc/hosts ]&&echo 1|| echo 0 1 #文件存在则为1,不存在则为0
[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
[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
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
[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、特殊条件测试表达式案例
[ 条件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" ],特别是使用[]的场景。 ·比较符号(例如=和!=)的两端一定要有空格。 ·“!=”和“=”可用于比较两个字符串是否相同。
[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)·比较符号两端也要有空格。
二元数字在[]中使用“<”、“>”非标准符号的比较。
[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
[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" }