好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

linux中shell test 条件表达式说明

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 
  • [root@localhost tmp]# [[ 1 -eq  $a ]] 
  • + [[ 1 -eq '' ]] 
  • [root@localhost tmp]# echo $?         
  • + echo 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 
  • [root@localhost tmp]# [[ abc == "a*c" ]] 
  • + [[ abc == /a/*/c ]] 
  • [root@localhost tmp]# echo $?            
  • + echo 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 
  • [root@localhost tmp]# [[ abc =~ "ab*c"  ]]   
  • + [[ abc =~ ab*c ]] 
  • [root@localhost tmp]# echo $? 
  • + echo 0 
  • [root@localhost tmp]# [[ abc =~ ab*c ]]   
  • + [[ abc =~ ab*c ]] 
  • [root@localhost tmp]# echo $?           
  • + echo 0  --phpfensi.com  
  • [root@localhost tmp]# [[ abc =~ /ab*c/ ]] 
  • + [[ abc =~ /ab*c/ ]] 
  • [root@localhost tmp]# echo $?             
  • + echo 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: 
  •      
  •       -o OPTION      True if the shell option OPTION is enabled. 
  •       ! EXPR  True if expr is false. 
  •       EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. 
  •       EXPR1 -o EXPR2 True if either expr1 OR expr2 is true. 
  •      
  •       arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne, 
  • -lt, -le, -gt, or -ge. 
  •      
  •     Arithmetic binary operators return true if ARG1 is equal, not-equal, 
  •     less-than, less-than-or-equal, greater-than, or greater-than-or-equal 
  •     than ARG2. 
  •      
  •     Exit Status: 
  •     Returns success if EXPR evaluates to true; fails if EXPR evaluates to 
  •     false or an invalid argument is given. 
  •     -a file 

    相关参考:

  • 如果 file 存在则为真。 
  • -b file 
  • 如果 file 存在且为块设备则为真。 
  • -c file 
  • 如果 file 存在且为字符设备则为真。 
  • -d file 
  • 如果 file 存在且是一个目录则为真。 
  • -e file 
  • 如果 file 存在则为真。 
  • -f file 
  • 如果 file 存在且为普通文件则为真。 
  • -g file 
  • 如果 file 存在且是设置组ID的 (sgid) 则为真。 
  • -h file 
  • 如果 file 存在且为符号链接则为真。 
  • -k file 
  • 如果 file 存在且设置了 ‘‘sticky’’ 位 (粘滞位) 则为真。 
  • -p file 
  • 如果 file 存在且是一个命名管道 (FIFO) 则为真。 
  • -r file 
  • 如果 file 存在且可读则为真。 
  • -s file 
  • 如果 file 存在且大小大于零则为真。 
  • -t fd  如果文件描述符 fd 是打开的且对应一个终端则为真。 
  • -u file 
  • 如果 file 存在且是设置用户ID的 (suid) 则为真。 
  • -w file 
  • 如果 file 存在且可写则为真。 
  • -x file 
  • 如果 file 存在且可执行则为真。 
  • -O file 
  • 如果 file 存在且为有效用户ID所拥有则为真。 
  • -G file 
  • 如果 file 存在且为有效组ID所拥有则为真。 
  • -L file 
  • 如果 file 存在且为符号链接则为真。 
  • -S file 
  • 如果 file 存在且为套接字则为真。 
  • -N file 
  • 如果 file 存在且上次读取后被修改过则为真。 
  • file1 -nt file2 
  • 如果 file1 比 file2 要新 (根据修改日期),或者如果 file1 存在而 file2 不存在,则为真。 
  • file1 -ot file2 
  • 如果 file1 比 file2 更旧,或者如果 file1 不存在而 file2 存在,则为真。 
  • file1 -ef file2 
  • 如果 file1 和 file2 指的是相同的设备和 inode 号则为真。 
  • -o optname 
  • 如果启用了 shell 选项 optname 则为真。参见下面对内建命令 set 的 -o 选项的描述中的选项列表。 
  • -z string 
  • 如果 string 的长度为 0 则为真。 
  • -n string 
  • string 如果 string 的长度非 0 则为真。 
  • string1 == string2 
  • 如果字符串相等则为真。= 可以用于使用 == 的场合来兼容 POSIX 规范。 
  • string1 != string2 
  • 如果字符串不相等则为真。 
  • string1 < string2 
  • 如果 string1 在当前语言环境的字典顺序中排在 string2 之前则为真。 
  • string1 > string2 
  • 如果 string1 在当前语言环境的字典顺序中排在 string2 之后则为真。 
  • arg1 OP arg2 
  • OP 是 -eq, -ne, -lt, -le, -gt, 或 -ge 之一。这些算术二进制操作返回真,如果 arg1 与 arg2 分别是相等,不等,小于,小于或等于,大于,大于或等于关系 。  Arg1   和 
  • arg2 可以是正/负整数。
  •  

     

    查看更多关于linux中shell test 条件表达式说明的详细内容...

  •   阅读:59次