conditional expressions are used by the [[ compound command and the test and [ builtin commands.
arithmetic expression
共有三个 [[,test,[
Shell中[和[[的异同
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 $?
0
if [[ "$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.658s
user 0m0.558s
sys 0m0.100s
$ time (for m in {1..100000}; do [ -d . ];done;)
real 0m0.609s
user 0m0.524s
sys 0m0.085s
$ time (for m in {1..100000}; do [[ -d . ]];done;)
real 0m0.311s
user 0m0.275s
sys 0m0.036s
不考虑对低版本bash和对sh的兼容的情况下,用[[]]是兼容性强,而且性能比较快,在做条件运算时候,可以使用该运算符。
####[[ ... ]]进行算术扩展,而[ ... ]不做
[root@250-shiyan ~]# [ 99+1 -eq 100 ]&&echo 100||echo 1
-bash: [: 99+1: integer expression expected
1
[root@250-shiyan ~]# [ $((99+1)) -eq 100 ]&&echo 100||echo 1
100
[root@250-shiyan ~]# [ $((99+1)) -eq 1001 ]&&echo 100||echo 1
1
[root@250-shiyan ~]# [[ 99+1 -eq 100 ]]&&echo 100||echo 1
100
[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 false
false
####下面的写法是错误的
[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 false
true
[root@250-shiyan ~]# [ 1 > 2 -a b > a ]&&echo true||echo false
true
[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 d
w
[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 false
false
[root@250-shiyan ~]# [ 4 -lt 2 -a b != a ]&&echo true||echo false
false
[root@250-shiyan ~]# [ 4 -lt 2 -o b != a ]&&echo true||echo false
true
[root@250-shiyan ~]# [ 1 -gt 2 -o b != a ]&&echo true||echo false
true
[root@250-shiyan ~]# [ 1 -gt 2 -o b != b ]&&echo true||echo false
false
[ -x /etc/passwd ]
[ EXPR ]
数值测试
ARG1 -eq ARG2
ARG1 -ne ARG2
ARG1 -lt ARG2
ARG1 -le ARG2
ARG1 -gt ARG2
ARG1 -ge ARG2
字符串测试
空
-z string
非空
-n string
string
等于
str1 = str2
不等于
str1 != str2
特征测试
These options test other file characteristics.特征即是说存在,大小,
-e file
-s file
file1 -nt file2
file1 -ot file2
file1 -ef file2
访问权限测试
-g file sgid
-k file stick位
-u file suid
-rwx file 读写执行
文件类型测试
连接测试
!EXPR
EXPR1 -a EXPR2
EXPR1 -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]# ll
total 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