三 Shell条件测试
逻辑运算符:与、或、非
布尔运算符
a 逻辑与;比较的多个条件要同时成立 才为真
o 逻辑或;比较的多个条件,只要有一个条件成立就为真
! 逻辑非;如果表达式为假,则测试结果为真
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
结论:-a 的运算规则:只有两端都为1才为真
真1 假 0
--------------
and 1*0=0 假
and 0*1=0 假
and 1*1=1
and 0*0=0
只有两端都为1才为真
结论:-o 的运算规则:只有两端都为0才为假,任何一端不为0都为真
or 1+0=1 真
or 1+1=2 真
or 0+1=1 真
or 0+0=0 假
两端都为0才为假,不为0就是真
逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
特别说明:
&& 前面的表达式为真,才会执行后面的代码
|| 前面的表达式为假,才会执行后面的代码
; 只用于分割命令或表达式
① 举例说明
数值比较
[root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
[root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
[root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
[root@server ~]# uid=`id -u`
[root@server ~]# test $uid -eq 0 && echo this is admin
this is admin
[root@server ~]# [ $(id -u) -ne 0 ] || echo this is admin
this is admin
[root@server ~]# [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
this is admin
[root@server ~]# su - stu1
[stu1@server ~]$ [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
this is not admin
类C风格的数值比较
注意:在(( ))中,=表示赋值;==表示判断
[root@server ~]# ((1==2));echo $?
[root@server ~]# ((1<2));echo $?
[root@server ~]# ((2>=1));echo $?
[root@server ~]# ((2!=1));echo $?
[root@server ~]# ((`id -u`==0));echo $?
[root@server ~]# ((a=123));echo $a
[root@server ~]# unset a
[root@server ~]# ((a==123));echo $?
字符串比较
注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断
[root@server ~]# a='hello world';b=world
[root@server ~]# [ $a = $b ];echo $?
[root@server ~]# [ "$a" = "$b" ];echo $?
[root@server ~]# [ "$a" != "$b" ];echo $?
[root@server ~]# [ "$a" !== "$b" ];echo $? 错误
[root@server ~]# [ "$a" == "$b" ];echo $?
[root@server ~]# test "$a" != "$b";echo $?
test 表达式
[ 表达式 ]
[[ 表达式 ]]
思考:[ ] 和 [[ ]] 有什么区别?
[root@server ~]# a=
[root@server ~]# test -z $a;echo $?
[root@server ~]# a=hello
[root@server ~]# test -z $a;echo $?
[root@server ~]# test -n $a;echo $?
[root@server ~]# test -n "$a";echo $?
# [ '' = $a ];echo $?
-bash: [: : unary operator expected
2
# [[ '' = $a ]];echo $?
0
[root@server ~]# [ 1 -eq 0 -a 1 -ne 0 ];echo $?
[root@server ~]# [ 1 -eq 0 && 1 -ne 0 ];echo $?
[root@server ~]# [[ 1 -eq 0 && 1 -ne 0 ]];echo $?
② 逻辑运算符总结
符号;和&&和||都可以用来分割命令或者表达式 分号(;)完全不考虑前面的语句是否正确执行,都会执行;号后面的内容 &&符号,需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然 ||符号,需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后内容;反之亦然 如果&&和||一起出现,从左往右依次看,按照以上原则
范例1:&&和-a 与逻辑符脚本例子
#!/bin/bash
echo -n "请输入两个数字[格式为:m n]" :
read m n
#第一种写法
if [ ${m} -eq 1 ] && [ ${n} -eq 2];then
echo "good"
else
echo "bad"
fi
#第二种写法
if [ ${m} -eq 1 -a ${n} -eq 2];then
echo "good"
else
echo "bad"
fi
#第三种写法
if [[ ${m} -eq 1 && ${n} -eq 2]];then
echo "good"
else
echo "bad"
fi
&&和-a与逻辑符写法总结如下:
#第一种写法
if [ "${a}" = "a" ] && [ "${b}" = "b"];then
#第二种写法
if [ "${a}" = "a" -a "${b}" = "b"];then
#第三种写法
if [[ "${a}" = "a" && "${b}" = "b"]];then
#下面的写法不对
#if (("${a}" ="a" -a "${b}" = "b"));then
范例2:||和-o或逻辑符的脚本例子
[root@localhost ~]# echo $file1 $file2
/etc/services /etc/rc.local
[root@localhost ~]# [[ -z "$file1" || -z "$file2" ]]&& echo 1 || echo 0
0
[root@localhost ~]# [[ -z "$file1" || -n "$file2" ]]&& echo 1 || echo 0
1
[root@localhost ~]# [[ -z "$file1" || -n "$file2" ]] && echo 1 || echo 0
1
[root@localhost ~]# [ -z "$file1" -o -z "$file2" ] && echo 1 || echo 00
[root@localhost ~]# [ -n "$file1" -o -z "$file2" ] && echo 1 || echo 0
1
范例3:!非逻辑符的例子
[root@localhost ~]# [ ! "$file1" = "$file2" ] && echo 1 || echo 0
1
[root@localhost ~]# [ ! -z "$file1" || -n "$file2" ] && echo 1 || echo 0
-bash: [: missing `]'
-bash: -n: command not found
0
[root@localhost ~]# [[ ! -z "$file1" || -n "$file2" ]] && echo 1 || echo 0
1
[root@localhost ~]# [[ ! -z "$file1" || ! -n "$file2" ]] && echo 1 || echo 0
1
[root@localhost ~]# [[ ! -z "$file1" && ! -n "$file2" ]] && echo 1 || echo 0
0
例4:利用read和cat打印选择菜单
单级菜单
[root@localhost ~]#cat menu.sh
menu() {
cat <<END
1.[install lamp]
2.[install lnmp]
3.[install nfs]
4.[install rsync]
please input the num that you want:
END
}
menu
read a
echo "you selected $a"
多级菜单
[root@localhost ~]#cat multi_menu.sh
cat <<END
1.[install lamp]
2.[install lnmp]
3.[install nfs]
4.[install rsync]
please input the num that you want:
END
read a
[ $a -eq 1 ] &&{
cat <<END
[1.install apache]
[2.install mysql]
[3.install php]
END
}
read b
echo "you want to install $b.apache"
条件测试操作
在bash的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同的操作,有时也会通过与if等条件语句相结合,让我们可以方便的完成判断。
思考:何为真(true)?何为假(false)?
语法格式
test 选项 文件名或目录名
[ 选项 文件名或目录名 ]
[[ 选项 文件名或目录名 ]]
或者:
格式1: test <测试表达式> 格式2: [ test<测试表达式> ] 格式3: [[ test<测试表达式> ]] ;支持正则
更多判断,man test
去查看,很多的参数都用来进行条件判断
说明:
格式1和格式2是等价的。格式3是扩展的test命令,有网友推荐格式3,老男孩习惯使用格式2
提示:
在[[]]中可以使用通配符进行模式匹配。&&、||、>、<等操作符可以应用于[[]]中,但不能应用于[]中。
对整数进行关系运算,也可以使用shell的算术运算符(())。
格式1:test <测试表达式>
范例1:test 测试文件
[root@localhost ~]# test -f file && echo true || echo false false [root@localhost ~]# touch file [root@localhost ~]# test -f file && echo true || echo false true
范例2:test命令非(!)的写法
[root@localhost ~]# test ! -f file && echo true || echo false true [root@localhost ~]# touch file [root@localhost ~]# test ! -f file && echo true || echo false false
格式2:[<测试表达式>]
范例:[]
[root@localhost ~]# rm -f file [root@localhost ~]# [ -f file ] && echo 1 || echo 0 0 [root@localhost ~]# touch file [root@localhost ~]# [ -f file ] && echo 1 || echo 0 1 [root@localhost ~]# [ ! -f file ] && echo 1 || echo 0 0 [root@localhost ~]# [ -f file ] && echo 1 || echo 0 1 [root@localhost ~]# [ ! -f file ] && echo 1 || echo 0 0 [root@localhost ~]# rm -f file [root@localhost ~]# [ -f file ] && cat file [root@localhost ~]# [ ! -f file ] && cat file cat: file: 没有那个文件或目录
范例3:[[<测试表达式>]]
范例:[[]]
[root@localhost ~]# touch file [root@localhost ~]# [[ ! -f file ]] && echo 1 || echo 0 0 [root@localhost ~]# [[ -f file ]] && echo 1 || echo 0 1 [root@localhost ~]# [[ -f file && -f folder ]] && echo 1 || echo 0 0 [root@localhost ~]# [ -f file && -f folder ] && echo 1 || echo 0 bash: [: missing `]' 0 [root@localhost ~]# [ -f file -a -f folder ] && echo 1 || echo 0 0 [root@localhost ~]# ls -l file -rw-r--r--. 1 root root 0 4月 26 09:51 file [root@localhost ~]# touch folder [root@localhost ~]# [ -f file -a -f folder ] && echo 1 || echo 0 1
例子1:
#!/bin/bash test -e /file if [ $? -eq 0 ];then echo "目录/file存在" else echo " 目录/file不存在,现在为您自动创建" mkdir /file fi
例子:
#!/bin/bash [ -e /file ] if [ $? -eq 0 ];then echo "目录/file存在" else echo " 目录/file不存在,现在为您自动创建" mkdir /file fi
下面举一些条件测试的例子。为了清晰的显示测试结果,在屏幕上输出1(表示真)或0(表示假)表示测试结果
提示:这和前面的状态变量”$?”返回0为真不一样。
[root@localhost ~]# [ -f "$file1" ] && echo 1 || echo 0 #这是条件表达式的用法 [root@localhost ~]# if [ if "$file1" ];then echo 1;else echo 0;fi #这是if条件句的用法
提示:
1.以上两条语句的功能是等同的 2.变量$file加了双引号,可以防止很多意外的错误发生
test命令测试的用法
范例1:用test命令测试字符串
[root@localhost ~]# file1=/etc/services [root@localhost ~]# test -z "$file1" || echo 0 0 [root@localhost ~]# test -z "$file1" && echo 1 || echo 0 0 [root@localhost ~]# [ -z "$file1" ] && echo 1 || echo 0 0 [root@localhost ~]# test -n "$file1" && echo 1 || echo 0 1
范例2:用test命令测试整数比较
[root@localhost ~]# test "dd" = "ff" && echo 1 || echo 0 0 [root@localhost ~]# test "dd" = "dd" && echo 1 || echo 0 1 [root@localhost ~]# test "dd" != "dd" && echo 1 || echo 0 0
结论:test命令测试的功能很强大,但是和[],[[]]之前都是重合的功能,因此,在实际工作中选择一种适合我们的语法就OK了,其他的语法,别人写的脚本可以阅读就可以了。
文件状态测试
语法格式
[操作符 文件或目录]
操作符:
-e 不管是文件还是目录,只要存在,条件就成立 -d 判断对象是否为目录(Directory),是则为真 -f 判断对象是否为一般文件(file),是则为真 -w 判断对象是否有可写(Write)权限 ,是则为真
-x 判断对象是否有可执行(eXcute)权限 ,是则为真
-r 文件存在且有读权限,为真
-s 若文件存在且不为空,则为真
-L 若文件存在且为链接文件则为真
-f1 -nt f2 若文件f1比文件f2新则为真
-f1 -ot f2 若文件f1比文件f2旧则为真
㈠ 判断文件类型
判断参数 | 含义 |
---|---|
-e | 判断文件是否存在(任何类型文件) |
-f | 判断文件是否存在并且是一个普通文件 |
-d | 判断文件是否存在并且是一个目录 |
-L | 判断文件是否存在并且是一个软连接文件 |
-b | 判断文件是否存在并且是一个块设备文件 |
-S | 判断文件是否存在并且是一个套接字文件 |
-c | 判断文件是否存在并且是一个字符设备文件 |
-p | 判断文件是否存在并且是一个命名管道文件 |
-s | 判断文件是否存在并且是一个非空文件(有内容) |
举例说明:
三种语法格式:
test -e file 只要文件存在条件为真
[ -d /shell01/dir1 ] 判断目录是否存在,存在条件为真
[ ! -d /shell01/dir1 ] 判断目录是否存在,不存在条件为真
[[ -f /shell01/1.sh ]] 判断文件是否存在,并且是一个普通的文件
㈡ 判断文件权限
判断参数 | 含义 |
---|---|
-r | 当前用户对其是否可读 |
-w | 当前用户对其是否可写 |
-x | 当前用户对其是否可执行 |
-u | 是否有suid,高级权限冒险位 |
-g | 是否sgid,高级权限强制位 |
-k | 是否有t位,高级权限粘滞位 |
㈢ 判断文件新旧
说明:这里的新旧指的是文件的修改时间。
判断参数 | 含义 |
---|---|
file1 -nt file2 | 比较file1是否比file2新 |
file1 -ot file2 | 比较file1是否比file2旧 |
file1 -ef file2 | 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode |
常用文件测试操作符的记忆方法
[root@localhost ~]# echo f=file f=file [root@localhost ~]# echo d=directory d=directory [root@localhost ~]# echo s=size s=size [root@localhost ~]# echo e=exist e=exist [root@localhost ~]# echo r=read r=read [root@localhost ~]# echo w=write w=write [root@localhost ~]# echo x=executale x=executale [root@localhost ~]# echo nt="newer than" nt=newer than [root@localhost ~]# echo ot="older than" ot=older than 提示:不用纠结到底是不是全拼,只要有助于记忆就是好的方法
文件测试举例
首先定义file1和file2两个变量,并分别赋予两个系统文件路径及文件名的值。
[root@localhost ~]# file1=/etc/services;file2=/etc/rc.local #分号用于分隔两个命令 [root@localhost ~]# echo $file1 $file2 /etc/services /etc/rc.local
范例1:对单个文件的测试:
[root@localhost ~]# [ -f "$file1" ] && echo 1 || echo 0 1 #文件存在并且为普通文件所以为真(1) [root@localhost ~]# [ -d "$file1" ] && echo 1 || echo 0 0 #是文件但不是目录所以为假(0) [root@localhost ~]# [ -s "$file1" ] && echo 1 || echo 0 1 #文件存在且大小不为0,所以为真(1) [root@localhost ~]# [ -e "$file1" ] && echo 1 || echo 0 1 #文件存在所以为真(1) [root@localhost ~]# dir1=/etc [root@localhost ~]# [ -e "$dir1" ] && echo 1 || echo 0 1 [root@localhost ~]# [ -w /etc/services ] && echo 1 || echo 0 1 [root@localhost ~]# su - zgy [zgy@localhost ~]$ [ -w /etc/services ] && echo 1 || echo 0 0 [zgy@localhost ~]$ ll /etc/services -rw-r--r--. 1 root root 641020 10月 2 2012 /etc/services
特殊例子:如果变量不加双引号,结果可能就不正确。
[zgy@localhost ~]$ [ -f "$file7" ]&& echo 1 || echo 0 0 [zgy@localhost ~]$ echo $file7 [zgy@localhost ~]$ [ -f $file7 ]&& echo 1 || echo 0 1 #说明$file7不存在还返回1 [zgy@localhost ~]$ [ -f "$file7" ]&& echo 1 || echo 0 0 [zgy@localhost ~]$ file7=/etc/hosts [zgy@localhost ~]$ [ -f $file7 ]&& echo 1 || echo 0 1 [zgy@localhost ~]$ [ ! -f $file7 ]&& echo 1 || echo 0 0 [zgy@localhost ~]$ [ -f "$file7" ]&& echo 1 || echo 0 1 [zgy@localhost ~]$ [ ! -f "$file7" ]&& echo 1 || echo 0 0
范例2:把变量内容换成文件实体
[zgy@localhost ~]$ [ -f /etc/service ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ -f /etc/services ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ -f "/etc/service" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ -f "/etc/services" ] && echo 1 || echo 0 1
范例3(生产):生产环境系统nfs启动脚本的条件测试的内容
[zgy@localhost ~]$ less /etc/init.d/nfs # Source networking configuration. [ -f /etc/sysconfig/network ] && . /etc/sysconfig/network #如果/etc/sysconfig/network文件存在就加载文件 # Check for and source configuration file otherwise set defaults [ -f /etc/sysconfig/nfs ] && . /etc/sysconfig/nfs #如果/etc/sysconfig/nfs文件存在就加载文件
特别提示:系统脚本是学习编程的第一标杆。要参考,虽然有时也不是很规范。
范例4:读文件单中括号[]与或非测试
可用于(-a和&&)、或(-o和||)、非(!)将多个条件表达式连接起来,接着上面的变量测试。
[root@localhost ~]# file1=/etc/services;file2=/etc/rc.local [root@localhost ~]# echo $file1 $file2 [root@localhost ~]# [ -f "$file1" -o -e "$file2" ] && echo 1 || echo 0 1 [root@localhost ~]# [ -f "$file1" -a -e "$file2" ] && echo 1 || echo 0 1 [root@localhost ~]# [root@localhost ~]# [ -f "$file1" || -e "$file2" ] && echo 1 || echo 0 -bash: [: missing `]' #用法不对了,你知道哪里不对吗? -bash: -e: command not found 0
提醒:
1、”-a”和”-o”逻辑操作符用于[]中使用。 2、“&&”和”||”逻辑操作符用于[[]]中使用 3、注意括号两端,必须要有空格。
如果你很犟,非要单中括号加&&或||那就用如下方法:
[root@localhost ~]# [ -f "$file1" ] ||[ -e "$file2" ] && echo 1 || echo 0 1 [root@localhost ~]# [ -f "$file1" ] &&[ -e "$file2" ] && echo 1 || echo 0 1
范例5:双中括号多条件文件或非测试
[root@localhost ~]# [[ -f "$file1" || -e "$file2" ]] && echo 1 || echo 0 1 [root@localhost ~]# [[ -f "$file1" && -e "$file2" ]] && echo 1 || echo 0 1 [root@localhost ~]# [[ -e "$file1" -a -f "$file2" ]] && echo 1 || echo 0 -bash: syntax error in conditional expression -bash: syntax error near `-a' #用法又不对了,你知道哪里不对吗?;有时候照葫芦画瓢也不行 [root@localhost ~]# [[ -f "$file1" ]] -a [[ -e "$file2" ]] && echo 1 || echo 0 -bash: syntax error near unexpected token `-a'
系统案例:
[root@localhost ~]# less /etc/init.d/nfs [ -n $RPCNFSDARGS -a "$NFSD_MODULE" != "noload" ] && { [ -x /sbin/modprobe ] && /sbin/modprobe nfsd }
范例6:系统bind启动脚本举例:named服务
范例7:简易高效的文件判断例子
在做测试判断时,不一定非要按照前面的方法。直接用后者做测试判断有时更简洁。
范例:
[zgy@localhost ~]$ file1=/etc/services [zgy@localhost ~]$ [ -f "$file1" ] && echo 1 #条件成立返回1 1 [zgy@localhost ~]$ [ -f "$file3" ] || echo 0 #条件不成立返回0 0
系统范例:/etc/init.d/nfs
[root@localhost ~]# less /etc/init.d/nfs [ -x /usr/sbin/rpc.nfsd ] || exit 5 [ -x /usr/sbin/rpc.mountd ] || exit 5 [ -x /usr/sbin/exportfs ] || exit 5
整数值比较
格式:
[整数值1 操作符 整数值2]
操作符:
-eq 等于(Equal) -ge 大于或等于(Greater or Equal) -gt 大于(Greater Than) -le 小于或等于(Lesser or Equal) -lt 小于(Lesser Than) -ne 不等于(Not Equal)
提示:
1)”<”符号意思是小于,例if[[ “$a”< “$b” ]];if [[ “$a”\< “$b” ]]。在单[]中需要转义,因为shell也用<和>重定向。 2)”>”符号意思是小于,例if[[ “$a”>“$b” ]];if [[ “$a”\>“$b” ]]在单[]中需要转义,因为shell也用<和>重定向。 3)”=”符号意思是等于,例if[[ “$a”=“$b” ]];if [[ “$a”“$b” ]]在单[]中不需要转义。
特别提示
经过实践,”=”和”!=”在[]中使用不需要转义,包含”>”和”<”的符号在[]中使用需要转义,对于不转义的结果未必会报错,但是结果可能不会对。
范例1:二元数字比较
[root@localhost ~]# [ 2 > 1 ] && echo 1 || echo 0 1 [root@localhost ~]# [ 2 < 1 ] && echo 1 || echo 0 1 #这里的结果逻辑不对,条件不成立,应该返回0 [root@localhost ~]# [ 2 \< 1 ] && echo 1 || echo 0 0 #转义后是正确的 [root@localhost ~]# [ 2 \> 1 ] && echo 1 || echo 0 1 [root@localhost ~]# [ 2 -gt 1 ] && echo 1 || echo 0 1 [root@localhost ~]# [ 2 -lt 1 ] && echo 1 || echo 0 0 [root@localhost ~]# [[ 2 > 1 ]] && echo 1 || echo 0 1 [root@localhost ~]# [[ 2 < 1 ]] && echo 1 || echo 0 0 [root@localhost ~]# [ 2 = 1 ] && echo 1 || echo 0 0 [root@localhost ~]# [ 2 = 2 ] && echo 1 || echo 0 1 [root@localhost ~]# [ 2 != 2 ] && echo 1 || echo 0 0 提示:经过实践,”=”和”!=”在[]中石油不需要转移也可以。 [root@localhost ~]# [[ 2 -lt 1 ]] && echo 1 || echo 0 0 [root@localhost ~]# [[ 2 -gt 1 ]] && echo 1 || echo 0 1
范例2:二元字符比较
[root@localhost ~]# [ "a" > "bc" ] && echo 1 || echo 0 1 [root@localhost ~]# [ "a" < "bc" ] && echo 1 || echo 0 1 #上面两个条件不一样,但结果是一样,虽然没报语法错误,但显然不对 [root@localhost ~]# [ "a" \> "bc" ] && echo 1 || echo 0 0 [root@localhost ~]# [ "a" \< "bc" ] && echo 1 || echo 0 1 #加上对比较的转义后,逻辑上显示正确了
范例1:整数条件测试举例
[root@localhost ~]# a1=10;a2=13 [root@localhost ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0 0 #条件不成立,返回0 [root@localhost ~]# [ $a1 -gt $a2 ] && echo 1 || echo 0 0 [root@localhost ~]# [ $a1 -lt $a2 ] && echo 1 || echo 0 1 [root@localhost ~]# [ $a1 -le $a2 ] && echo 1 || echo 0 1 [root@localhost ~]# [ $a1 -ge $a2 ] && echo 1 || echo 0 0 [root@localhost ~]# [ $a1 -ne $a2 ] && echo 1 || echo 0 1 [root@localhost ~]# a=0001 [root@localhost ~]# b=100 [root@localhost ~]# [ "$a" -ge "$b" ] && echo 1 || echo 0 0 [root@localhost ~]# [ "$a" -le "$b" ] && echo 1 || echo 0 1
范例2:直接通过数字运算符比较
[root@localhost ~]# [[ $a1 = $a2 ]] && echo 1 ||echo 0 #功能同上,条件不成立,返回0 0 [root@localhost ~]# [[ $a1 == $a2 ]] && echo 1 ||echo 0 #功能同上,条件不成立,返回0 0 [root@localhost ~]# (($a1>$a2)) && echo 1 || echo 0 0 [root@localhost ~]# [ $a1 > $a2 ]&& echo 1 || echo 0 #没报错,但结果不对 1 [root@localhost ~]# [ $a1 \> $a2 ]&& echo 1 || echo 0 #加转移或[[]] 0 [root@localhost ~]# [[ $a1 > $a2 ]] && echo 1|| echo 0 0 [root@localhost ~]# (( $a1<$a2 )) && echo 1 || echo 0 1 [root@localhost ~]# (( $a1>$a2 )) && echo 1 || echo 0 0 [root@localhost ~]# (( a1>a2 )) && echo 1 || echo 0 0 [root@localhost ~]# (( a1<a2 )) && echo 1 || echo 0 1
字符串比较
字符串测试操作符的作用:比较两个字符串是否相同、字符串长度是否为零,字符串是否为NULL(注:bash区分零长度字符串和空字符串)等。
“=”比较两个字符串是否相同,与==等价,如if[ “$a” = “$b” ],其中$a这样的变量最好用””括起来,因为如果中间有空格,*等符号就可能出错了,当然更好的方法就是[ “${a}”=”${b}” ]。”!=”比较两个字符串是否相同,不同则为”是”。
字符串测试操作符提示:
1)-n 比较字符串长度是否不为0,如果不为0则为真,如:[ -n “$myvar” ] 2)-z 比较字符串长度是否等于0,如果等于0则为真,如[ -z “$myvar” ] 3)特别注意,对于以上表格中的组非常测试操作符号,如[ -n “$myvar” ],要把字符串用””引起来。
或:
判断参数 | 含义 |
---|---|
-z | 判断是否为空字符串,字符串长度为0则成立 |
-n | 判断是否为非空字符串,字符串长度不为0则成立 |
string1 = string2 | 判断字符串是否相等 |
string1 != string2 | 判断字符串是否相不等 |
格式1:
[字符串1 操作符 字符串2]
操作符:
== 测试是否相等,相等为真,不等为假 != 测试是否不等,不等为真,等为假 > 测试是否大于,大于为真,不大于为假 < 测试是否小于,小于为真,不小于为假
格式2:
[操作符 字符串]
操作符:
-z 测试指定字符串是否为空,空为真,非空则为假
-n 测试指定字符串是否非空,非空则真,空则假(相当于!-z)
字符串测试操作符提示:
1)-n 比较字符串长度是否不为0,如果不为0则为真,如:[ -n “$myvar” ] 2)-z 比较字符串长度是否等于0,如果等于0则为真,如[ -z “$myvar” ] 3)特别注意,对于以上表格中的组非常测试操作符号,如[ -n “$myvar” ],要把字符串用””引起来。
下面的$file并未定义,而$file1在上面测试中已定义
范例1:单条件字符串测试:
[root@localhost ~]# echo $file1 $file /etc/services [root@localhost ~]# [ -n "$file" ] && echo 1 || echo 0 0 #若串长度不为0则为真,因$file未定义长度为0,所以为假(0) [root@localhost ~]# [ -z "$file" ] && echo 1 || echo 0 1 #若串长度为0则为真,因$file未定义长度为0,所以为真(1) [root@localhost ~]# [ -z "$file1" ] && echo 1 || echo 0 0 #若串长度为0则为真,因$file1已定义长度,所以为假(0)
提示:去掉双引号看看
[root@localhost ~]# [ -z $file1 ] && echo 1 || echo 0 0 [root@localhost ~]# [ -z $file ] && echo 1 || echo 0 1
特别强调:字符串比较一定要加双引号
范例2:系统脚本/etc/init.d/nfs字符串测试的应用:
[ -z "$MOUNTD_NFS_V2" ] && MOUNTD_NFS_V2=default [ -z "$MOUNTD_NFS_V3" ] && MOUNTD_NFS_V3=default # Number of servers to be started by default [ -z "$RPCNFSDCOUNT" ] && RPCNFSDCOUNT=8
范例3:多条件字符串测试:
[zgy@localhost ~]$ echo $file1 $file2 /etc/services /etc/rc.local [zgy@localhost ~]$ [ -z "$file1" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ -z "$file1" -a -z "$file2" ] && echo 1 || echo 00 [zgy@localhost ~]$ [[ -z "$file1" && -z "$file2" ]] && echo 1 || echo 0 0 [zgy@localhost ~]$ [[ -z "$file1" || -z "$file2" ]] && echo 1 || echo 0 0 [zgy@localhost ~]$ [[ -z "$file1" || -n "$file2" ]] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ -z "$file1" -o -z "$file2" ] && echo 1 || echo 00 [zgy@localhost ~]$ [ -n "$file1" -o -z "$file2" ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ "$file1" = "$file2" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ "$file1" == "$file2" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ "$file1" !== "$file2" ] && echo 1 || echo 0 -bash: [: !==: binary operator expected 0 [zgy@localhost ~]$ [ "$file1" != "$file2" ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ ! "$file1" == "$file2" ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ ! "$file1" \> "$file2" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ ! "$file1" \< "$file2" ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ "${#file1}" = "${#file2}" ] && echo 1 || echo 0 1 [zgy@localhost ~]$ [ "${#file1}" != "${#file2}" ] && echo 1 || echo 0 0 [zgy@localhost ~]$ [ "${#file1}" \< "${#file2}" ] && echo 1 || echo 00 [zgy@localhost ~]$ echo ${#file1} 13 [zgy@localhost ~]$ echo ${#file2} 13
范例4:字符串测试bind系统启动脚本举例:named
if [ -n "$ROOTDIR" ]; then ROOTDIR=`echo $ROOTDIR | sed 's#//*#/#g;s#/$##'`; rdl=`/usr/bin/readlink $ROOTDIR`; if [ -n "$rdl" ]; then ROOTDIR="$rdl"; fi; fi