conditional expressions are used by the [[ compound command and the test and [ builtin commands.
arithmetic expression
共有三个 [[,test,[
test判断方式: [ ] 不支持Shell中提供的各种通配符
状态判断的方式:[[ expr ]],和test不同的是,该方式中的表达式支持通配符,在[[ expression ]]中,expression可以包含&&(逻辑与)和||(逻辑或)let命令的判断方式: (( expr ))test是Shell中提供的内置命令,主要用于状态的检验,如果结果为0,表示成功,否则表示失败。
需要注意的是test命令不支持Shell中提供的各种通配符,如: /> name=stephen /> test $name = [Ss]tephen /> echo $? 1在Shell中还提供了另外一种用于状态判断的方式:[[ expr ]],和test不同的是,该方式中的表达式支持通配符,如: /> name=stephen /> [[ $name == [Ss]tephen ]] /> echo $? 0if [[ "$s" -gt "0" || "$r" -gt "0" ]]
#在[[ expression ]]中,expression可以包含&&(逻辑与)和||(逻辑或)。 /> [[ $name == [Ss]tephen && $friend == "Jose" ]] /> echo $? 1 /> shopt -s extglob #打开Shell的扩展匹配模式。 /> name=Tommy # "[Tt]o+(m)y"的含义为,以T或t开头,后面跟着一个o,再跟着一个或者多个m,最后以一个y结尾。 /> [[ $name == [Tt]o+(m)y ]] /> echo $? 0 /> help [[ 出现帮助信息,但下面的help ((,却提示错误,后来发现是这样的,help \(\( 在Shell中还提供了let命令的判断方式: (( expr )),该方式的expr部分,和C语言提供的表达式规则一致,如: /> x=2 /> y=3 /> (( x > 2 )) /> echo $? 1 /> (( x < 2 )) /> echo $? 0 /> (( x == 2 && y == 3 )) /> echo $? 0 /> (( x > 2 || y < 3 )) /> echo $? 1
bash的条件表达式中有三个几乎等效的符号和命令:test,[]和[[]]。通常,大家习惯用if [];then这样的形式。而[[]]的出现,根据ABS所说,是为了兼容><之类的运算符。以下是比较它们性能,发现[[]]是最快的。
$ time (for m in {1..100000}; do test -d .;done;)real 0m0.658suser 0m0.558ssys 0m0.100s$ time (for m in {1..100000}; do [ -d . ];done;)real 0m0.609suser 0m0.524ssys 0m0.085s$ time (for m in {1..100000}; do [[ -d . ]];done;)real 0m0.311suser 0m0.275ssys 0m0.036s不考虑对低版本bash和对sh的兼容的情况下,用[[]]是兼容性强,而且性能比较快,在做条件运算时候,可以使用该运算符。####[[ ... ]]进行算术扩展,而[ ... ]不做
[root@250-shiyan ~]# [ 99+1 -eq 100 ]&&echo 100||echo 1-bash: [: 99+1: integer expression expected1[root@250-shiyan ~]# [ $((99+1)) -eq 100 ]&&echo 100||echo 1100[root@250-shiyan ~]# [ $((99+1)) -eq 1001 ]&&echo 100||echo 1
1[root@250-shiyan ~]# [[ 99+1 -eq 100 ]]&&echo 100||echo 1100[root@250-shiyan ~]# [[ 99+1 -eq 1001 ]]&&echo 100||echo 1
1操作符有!,(),-a,-o,&&,||。单括号[是-a,-o,双括号[[是&&,||
####由于"[["是关键字,不会做命令行扩展,所以在[[中"<"与">"不需转义,但是相对的语法就稍严格些。例如在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在[[ ... ]]则不允许这样做;
注意:[[]] 运算符只是[]运算符的扩充。能够支持<,>符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| &&
[root@250-shiyan ~]# [[ 1 < 2 && b > a ]]&&echo true||echo false
true[root@250-shiyan ~]# [[ 1 > 2 && b > a ]]&&echo true||echo falsefalse####下面的写法是错误的
[root@250-shiyan ~]# [ 1 > 2 && b > a ]&&echo true||echo false-bash: [: missing `]'false[root@250-shiyan ~]# [ 1 > 2 -o b > a ]&&echo true||echo falsetrue[root@250-shiyan ~]# [ 1 > 2 -a b > a ]&&echo true||echo falsetrue[root@localhost ~]# [ 1 -eq 1 ] && echo 'ok'
ok[root@localhost ~]# [ 2 < 1 ] && echo 'ok' -bash: 2: No such file or directory[root@localhost ~]# [ 2 \< 1 ] && echo 'ok'[root@localhost ~]# [ 2 -gt 1 -a 3 -lt 4 ] && echo 'ok'ok [root@localhost ~]# [ 2 -gt 1 && 3 -lt 4 ] && echo 'ok' -bash: [: missing `]'注意:在[] 表达式中,常见的>,<需要加转义字符,表示字符串大小比较,以acill码位置作为比较。 不直接支持<>运算符,还有逻辑运算符|| && 它需要用-a[and] –o[or]表示####[ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以字符串比较操作符">" 与"<"必须转义,否则就变成IO重定向了;
[root@250-shiyan ~]# [ 1 -gt 2 -o b \< a ]&&echo w||echo d
d[root@250-shiyan ~]# [ 1 -gt 2 -o b \< c ]&&echo w||echo dw[root@250-shiyan ~]# [ 1 -lt 2 -a b != a ]&&echo true||echo false
true[root@250-shiyan ~]# [ 1 -lt 2 -a b != b ]&&echo true||echo falsefalse[root@250-shiyan ~]# [ 4 -lt 2 -a b != a ]&&echo true||echo falsefalse[root@250-shiyan ~]# [ 4 -lt 2 -o b != a ]&&echo true||echo falsetrue[root@250-shiyan ~]# [ 1 -gt 2 -o b != a ]&&echo true||echo falsetrue[root@250-shiyan ~]# [ 1 -gt 2 -o b != b ]&&echo true||echo falsefalse[ -x /etc/passwd ][ EXPR ]数值测试ARG1 -eq ARG2ARG1 -ne ARG2ARG1 -lt ARG2ARG1 -le ARG2ARG1 -gt ARG2ARG1 -ge ARG2字符串测试空-z string非空-n stringstring等于str1 = str2不等于str1 != str2特征测试These options test other file characteristics.特征即是说存在,大小,-e file-s filefile1 -nt file2file1 -ot file2file1 -ef file2访问权限测试-g file sgid-k file stick位-u file suid-rwx file 读写执行文件类型测试连接测试!EXPREXPR1 -a EXPR2EXPR1 -o EXPR2-d 目录 -r 读 -w 写 -x 执行 -f 常规文件 -L 符号链接1)判断表达式 if test (表达式为真) if test !表达式为假 test 表达式1 -a 表达式2 两个表达式都为真 test 表达式1 -o 表达式2 两个表达式有一个为真 2)判断字符串 test –n 字符串 字符串的长度非零 test –z 字符串 字符串的长度为零 test 字符串1=字符串2 字符串相等 test 字符串1!=字符串2 字符串不等 3)判断整数 test 整数1 –eq 整数2 整数相等 test 整数1 –ge 整数2 整数1大于等于整数2 test 整数1 –gt 整数2 整数1大于整数2 test 整数1 –le 整数2 整数1小于等于整数2 test 整数1 –lt 整数2 整数1小于整数2 test 整数1 –ne 整数2 整数1不等于整数2 4)判断文件权限及类型
-g -u -k
-G -O
-rwx
test File1 –ef File2 两个文件具有同样的设备号和i结点号 test File1 –nt File2 文件1比文件2 新 test File1 –ot File2 文件1比文件2 旧 test –b File 文件存在并且是块设备文件 test –c File 文件存在并且是字符设备文件 test –d File 文件存在并且是目录 test –e File 文件存在 test –f File 文件存在并且是正规文件 test –g File 文件存在并且是设置了组ID test –G File 文件存在并且属于有效组ID test –h File 文件存在并且是一个符号链接(同-L) test –k File 文件存在并且设置了sticky位 test –b File 文件存在并且是块设备文件 test –L File 文件存在并且是一个符号链接(同-h) test –o File 文件存在并且属于有效用户ID test –p File 文件存在并且是一个命名管道 test –r File 文件存在并且可读 test –s File 文件存在并且是一个套接字 test –t FD 文件描述符是在一个终端打开的 test –u File 文件存在并且设置了它的set-user-id位 test –w File 文件存在并且可写 test –x File 文件存在并且可执行test一般有两种格式,即:test condition或[ condition ]使用方括号时,要注意在条件两边加上空格。[root@localhost script]# lltotal 8-rw-r--r-- 1 root root 1895 Dec 29 20:04 passwd-rw-r--r-- 1 root root 263 Dec 28 12:12 user[root@localhost script]# [ -w passwd ][root@localhost script]# echo $?0[root@localhost script]# test -x passwd[root@localhost script]# echo $?1