zoukankan      html  css  js  c++  java
  • shell测试命令test、[ ]、[[ ]]

    test可用于测试表达式,支持测试的范围包括:字符串比较,算术比较,文件存在性、属性、类型等判断。例如,判断文件是否为空、文件是否存在、是否是目录、变量是否大于5、字符串是否等于"longshuai"、字符串是否为空等等。在shell中,几乎所有的判断都使用test实现。

    其中[]完全等价于test,只是写法不同。双中括号[[]]基本等价于[],它支持更多的条件表达式,还允许在双中括号内使用逻辑运算符"&&"、"||"、"!"和"()",但这些使用单中括号都能实现,只不过多写几个单中括号而已。单中括号[]无法实现的功能是正则表达式匹配,而[[]]可以实现。因此,在能使用单中括号的情况下,无需考虑使用双中括号。

    test、[ ]以及[[ ]]都使用条件表达式来完成测试。test和[]用法虽简单,但语法比较复杂,反而是[[]]的语法较为简单。但不管如何,先解释条件表达式。

    1.1 条件表达式                                

    条件表达式 意义
    1.文件类检测,例如[ -e /tmp/a.log ]。如非特别说明,则所有文件类操作都会追踪到软链接的源文件。
    -e file 文件是否存在(exist)
    -f file 文件是否存在且为普通文件(file)
    -d file 文件是否存在且为目录(directory)
    -b file 文件是否存在且为块设备block device
    -c file 文件是否存在且为字符设备character device
    -S file 文件是否存在且为套接字文件Socket
    -p file 文件是否存在且为命名管道文件FIFO(pipe)
    -L file 文件是否存在且是一个链接文件(Link)

    2. 文件属性检测,如test -r /tmp/a.log。如非特别说明,则所有文件类操作都会追踪到软链接的源文件。

    -r file 文件是否存在且当前用户可读
    -w file 文件是否存在且当前用户可写
    -x file 文件是否存在且当前用户可执行
    -u file 文件是否存在且设置了SUID
    -g file 文件是否存在且设置了SGID
    -k file 文件是否存在且设置了sbit(sticky bit)
    -s file 文件是否存在且大小大于0字节,即用于检测文件是否为非空白文件
    -N file 文件是否存在,且自上次read后是否被modify

    3. 两个文件之间的比较,如:test file1 -nt file2

    file1 -nt file2 (newer than)判断file1是否比file2新
    file1 -ot file2 (older than)判断file1是否比file2旧
    file1 -ef file2 equal file)判断file2与file2是否为同一文件,可用在判断hard link的判定上。主要意义在判定,两个文件是否均指向同一个分区上的同一个inode

    4. 两个整数之间的判定,支持正负数,但不支持小数。例如test n1 -eq n2

    int1 -eq int2 两数值相等(equal)
    int1 -ne int2 两数值不等(not equal)
    int1 -gt int2 n1大于n2(greater than)
    int1 -lt int2 n1小于n2(less than)
    int1 -ge int2 n1大于等于n2(greater than or equal)
    int1 -le int2 n1小于等于n2(less than or equal)

     5. 判定字符串

    -z string (zero)判定字符串是否为空?若string为空字符串,则为true

    string

    -n string

    判定字符串是否非空?若string为空字符串,则false。注:-n可省略

    string1 = string2

    string1 == string2

    string1和string2是否相同。相同则返回true。"=="和"="等价,但"="可移植性更好
    str1 != str2 str1是否不等于str2,若不等,则返回true
    str1 > str2 str1字母顺序是否大于str2,若大于,则返回true
    str1 < str2 str1字母顺序是否小于str2,若小于,则返回true

     6.逻辑运算符,例如:test -r filename -a -x filename

    -a或&& (and)两表达式同时为true时才为true。"-a"只能在test或[]中使用,&&只能在[[]]中使用
    -o或|| (or)两表达式任何一个true则为true。"-o"只能在test或[]中使用,||只能在[[]]中使用
    ! 对表达式取反
    ( ) 用于改变表达式的优先级,为了防止被shell解析,应该加上反斜线转义( )

    1.2 test和[ ]的用法说明                            

    test和[]的用法非常简单,但语法较复杂。它们是根据参数的个数来完成测试的,所以测试的结果也依赖于参数的个数。如下所述:

    (1).不带任何参数时,直接返回false。

    [root@localhost ~]# [ ];echo $?
    1

    (2).只有一个参数时,测试表达式采取的是[ arg ],根据条件表达式的说明,仅当arg为非空时返回true。

    [root@localhost ~]# test haha;echo $?
    0
    [root@localhost ~]# test $abcd;echo $?
    1
    [root@localhost ~]# test '';echo $?
    1

    (3).两个参数时,有几种情况:

    ①.第一个参数是单目条件运算符,包括文件类测试(如[ -e file1 ])和[ -n string ]、[ -z string ]。

    ②.第一个参数是"!"时,则只能是[ ! string ],等价于[ ! -n string ]。因为"!"是对条件表达式取反,所以当string为空时才true。

    ③第一个参数不是任何有效的操作符。将直接报错

    (4).三个参数时,也有几种情况:

    ①.使用了双目运算符,如[ file1 -nt file2 ],[ init1 -eq int2 ]以及[ string1 != string2 ]。

    ②.使用了逻辑运算符,如[ string1 -a string2 ]、[ ! -e file ]、[ ! -z string ]、[ ! -n string ]。

    ③.使用了括号,则只能是[ (string) ]。

    (5).四个参数以上时,则处理方法参照上面。如[ ! string1 == string2 ]、[ string1 == string2 -o string1 == string3 ]。

    无论参数数量多少个,总的来说还是对条件表达式的测试,所以最重要的还是条件表达式的逻辑结果。

    1.3 [[ ]]                                      

    [[]]基本等价于[],但有些功能写法更简洁,且[[]]提供了[]所不具备的正则表达式匹配。所以,[[]]的功能可以认为是[]和expr命令的相加。

    语法格式:

    [[ conditional_expression ]]

    除了以下特别注明的几项,其余用法等同[]。

    (1).当条件表达式中使用的运算符是"=="或"!="时,该运算符的右边会被当作pattern被匹配,"=="表示能匹配成功则返回0,"!="则相反。但此时只是通配符匹配,不支持正则表达式匹配。通配符包括:"*"、"?"和"[...]"。

    例如:

    [root@localhost ~]# [[ abc == a* ]];echo $?
    0
    [root@localhost ~]# [[ abc == a*d ]];echo $?
    1

    (2).当条件表达式中使用的运算符是"=~"时,该运算符的右边会被当作正则表达式的pattern被匹配。

    例如:

    [root@localhost ~]# [[ abc =~ aa* ]];echo $?
    0
    [root@localhost ~]# [[ abc =~ aa.* ]];echo $?
    1

    (3).除了可以使用逻辑运算符!和(),还可以使用&&、||,分别表示逻辑与和逻辑或,等价于[]的"-a"和"-o"。但是[[]]不再支持"-a"和"-o"。

    例如:

    [root@localhost ~]#  [[ 3 -eq 3 && 5 -eq 5 ]];echo $? 
    0

    总之,除了模式匹配和正则表达式匹配时需要使用[[]],其余时候建议使用[ ]。

    1.4 使用建议                                  

    1.无论是[]还是[[]],都建议对其内变量、字符串使用双引号包围。换句话说,能做字符串比较的时候,不要用数值比较。

    例如:

    [root@localhost ~]# name="Ma long"
    [root@localhost ~]# [ "$name" = "Ma long" ] && echo "yes" yes

    2.数值比较时,建议双方同时加0,避免变量为空时报错。

    例如,变量a为空,下面的表达式是错误的。因为它被shell解析后相当于[ -eq 7 ],而这是错误的语法。

    [root@localhost ~]# [ $a -eq 7 ]
    -bash: [: -eq: 期待一元表达式

    采取第一种建议,将$a使用引号包围的话,还是错的。因为被shell解析后相当于[ "" -eq 7 ],字符串和数值无法比较。注意这里的报错和上面的错误信息不一样。

    [root@localhost ~]# [ "$a" -eq 7 ]
    -bash: [: : 期待整数表达式

    所以最好的方法是将它改为字符串来测试。或者双方同时加0,由于此处有一方是常量数值,所以只需为变量部分加0即可。

    [root@localhost ~]# [ "$a" = "7" ]
    [root@localhost ~]# [ $((a+0)) -le 8 ]

    3.当变量可能为空的时候,强烈建议在变量的基础上加上其他辅助字符串。看过/etc/init.d下的脚本的人肯定都见过这种用法。

     上面的语句虽然能正确测试。其实更安全的方法是采用下面的形式:

    [root@localhost ~]# [ "a$a" = "a7" ]  # 判断a是否为7
    [root@localhost ~]# [ "a$a" = "a" ]   # 判断a是否为空
    [root@localhost ~]# [ ! -z "$a" -a "a$a" = "a7" ] # a不为空且a=7时才为真

    4.另外,在[]和[[]]中,每个地方都有空格。这不是书写建议,而是强制要求的格式。

  • 相关阅读:
    Java 基础
    Java 数据类型
    Spring 拦截器实现事物
    SSH 配置日记
    Hibernate 知识提高
    Jsp、Servlet
    leetcode 97. Interleaving String
    leetcode 750. Number Of Corner Rectangles
    leetcode 748. Shortest Completing Word
    leetcode 746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/liujunjun/p/12005502.html
Copyright © 2011-2022 走看看