shell test 条件表达式对于很多的开发者来讲都是不很理解了,下文我来为各位介绍一些关于linux中shell test 条件表达式的说明与例子.
条件表达式("CONDITIONAL EXPRESSIONS")
条件表达式用于 [[ 复合命令以及内建命令 test 和 [ 中,用来测试文件属性,进行字符串和算术比较,表达式使用下面的单目或二进制操作构造,如果某操作的任何 file 参数的形式是.
文件符号: 在info bash里的第[6.4 Bash Conditional Expressions]节里开头有一句话说明了shell条件判断的二个机制:
Conditional expressions are used by the `[[' compound command and the
`test' and `[' builtin commands.
机制一: 内置(builtin)的函数test(运算符[]),此部分完整的说明,可查看[4.1 Bourne Shell Builtins]
机制二: [[]],条件结构关健字,具体可查看[3.2.4.2 Conditional Constructs]
test跟[]是一回事,只不过一个以函数的形式,一个以成对操作符的形式出现,test包含6.4节条件表达式的表达形式,是函数就有参数,test对1、2、3.。。6等多个参数的判断分别进行定义,而[[]],大部分的功能跟[]是一样的,可以简单理解成[]的扩展,但对于参数的判断定义上,比test有更完整的定义,不容易出现[]中的错误,比如在-eq比较的右操作符中,[]要求右操作符不为空,否则报错,返回2,而[[]]则不会.
[root@localhost tmp]# [ 1 -eq $a ] + '[' 1 -eq ']' -bash: [: 1: unary operator expected [root@localhost tmp]# echo $? + echo 2 2 [root@localhost tmp]# [[ 1 -eq $a ]] + [[ 1 -eq '' ]] [root@localhost tmp]# echo $? + echo 1 1 这也是很多程序员喜欢用[[]]的原因,不容易出错,test的表达能力,[[]]扩展了二个功能.
1:pattern match,通配符匹配,采用双等号[==]
2:regex match,正则匹配,采用[=~]运算符号
首先说明下通配符匹配: 先说明一下[]里的==运算,[]也包括==比较,用于字符串相等比较,同样,==号在这里也不允许右操作符为空,否则报错.
[root@localhost tmp]# [ "abc" == $a ] + '[' abc == ']' -bash: [: abc: unary operator expected 解决办法是加个引号:
[root@localhost tmp]# [ "abc" == "$a" ] + '[' abc == '' ']' 而[[]]里的==,在3.2.4.2 里有介绍:
When the `==' and `!=' operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in *Note Pattern Matching::。。。 Any part of the pattern may be quoted to force it to be matched as a string. 这一段说明至少要注意二点:
1:[[]]里的==运算符,把所有右操作符都看做是一个pattern,==实际上不只是简单字符串比较,而是pattern match,即通配符匹配,具体的规则可以参考
3.5.8.1 Pattern Matching
2:最后一句:引号可以直接定义字符串,在3.5.8.1里也有一句话:The special pattern
characters must be quoted if they are to be matched literally.
即: pattern特殊字符为字符在引号里取消特殊定义
这也就能解释下边的二个例子的差别了:
[root@localhost tmp]# set -x + set -x [root@localhost tmp]# [[ abc == a*c ]] + [[ abc == a*c ]] [root@localhost tmp]# echo $? + echo 0 0 [root@localhost tmp]# [[ abc == "a*c" ]] + [[ abc == /a/*/c ]] [root@localhost tmp]# echo $? + echo 1 1 另外需要留意下: 在[[里,文档中提到:
Word splitting and filename expansion are not performed on the words between the `[[' and `]]'; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. 也就是说,在[[里,不进行bash命令解析中的[文字分割Word splitting ] 和 [文件名扩展filename expansion ]但还是进行了 [~符号扩展,参数和变量扩展,算术扩展,命令替换,进程替换,引号去除],所以不必担心上边例子中,a*b是否会扩展成目录下的文件名.
至于=~正则匹配,就没有什么特别是的了,右操作数直接定义成一个正则式子即是,这里正则的引号可用可不用(不能用/),因为在 [quote removal ]环节,对非扩展出来的引号做了去除处理,实际上有加引号与不加引号是一样的结果.
[root@localhost tmp]# [[ abc =~ 'ab*c' ]] + [[ abc =~ ab*c ]] [root@localhost tmp]# echo $? + echo 0 0 [root@localhost tmp]# [[ abc =~ "ab*c" ]] + [[ abc =~ ab*c ]] [root@localhost tmp]# echo $? + echo 0 0 [root@localhost tmp]# [[ abc =~ ab*c ]] + [[ abc =~ ab*c ]] [root@localhost tmp]# echo $? + echo 0 --phpfensi.com 0 [root@localhost tmp]# [[ abc =~ /ab*c/ ]] + [[ abc =~ /ab*c/ ]] [root@localhost tmp]# echo $? + echo 1 1 例子:
[root@LAMP test]# help test test: test [expr] Evaluate conditional expression. Exits with a status of 0 (true) or 1 (false) depending on the evaluation of EXPR. Expressions may be unary or binary. Unary expressions are often used to examine the status of a file. There are string operators as well, and numeric comparison operators. File operators: -a FILE True if file exists. -b FILE True if file is block special. -c FILE True if file is character special. -d FILE True if file is a directory. -e FILE True if file exists. -f FILE True if file exists and is a regular file. -g FILE True if file is set-group-id. -h FILE True if file is a symbolic link. -L FILE True if file is a symbolic link. -k FILE True if file has its `sticky' bit set. -p FILE True if file is a named pipe. -r FILE True if file is readable by you. -s FILE True if file exists and is not empty. -S FILE True if file is a socket. -t FD True if FD is opened on a terminal. -u FILE True if the file is set-user-id. -w FILE True if the file is writable by you. -x FILE True if the file is executable by you. -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. -N FILE True if the file has been modified since it was last read. FILE1 -nt FILE2 True if file1 is newer than file2 (according to modification date). FILE1 -ot FILE2 True if file1 is older than file2. FILE1 -ef FILE2 True if file1 is a hard link to file2. String operators: -z STRING True if string is empty. -n STRING STRING True if string is not empty. STRING1 = STRING2 True if the strings are equal. STRING1 != STRING2 True if the strings are not equal. STRING1 < STRING2 True if STRING1 sorts before STRING2 lexicographically. STRING1 > STRING2 True if STRING1 sorts after STRING2 lexicographically. Other operators: