<>

3.2. test

在许多程序设计语言中,我们都知道,在定义了变量的值或者是传递参数后,都需要测试这变量的值和参数值。shell 环境下的测试命令像其它 shell 命令一样都会设置返回的状态,实际上,test命令是一个 shell 内建命令!

shell 内建命令test根据表达式expr的运算结果返回0(真)或者是1(假)。你也可以使用[ ],test expr[ expr ]是等价的。你即可以通过变量 $? 来测试测试操作的返回值;也可以把返回值直接与&&、||连用;当然后面我们还会涉及到通过多个条件结构来测试返回值。

Example 3.1. 一些简单的 tests

[user@domain ~]$ test 3 -gt 4 && echo True || echo false
false
[user@domain ~]$ [ "abc" != "def" ];echo $?
0
[user@domain ~]$ test -d "$HOME" ;echo $?
0

Example 3.1, “一些简单的 tests”的第一个例子中,-gt操作符对两个数值进行算术比较。在第二个例子中,test的变形[ ]则是比较不等式两边的字符串。在最后一个例子中,是通过一元操作符-d来测试变量HOME变量的值是否是一个正常的目录。

你可以通过-eq、-ne、-lt、-le、-gt或者是-ge来比较算术值,它们分别表示相等、不相等、小于、小于等于、大于或者是大于等于。

同样你也可以用=!=比较字符串相等和不等,或者通过<>测试第一个字符串是否排在第二个字符串的前边或后边,通过一元操作符-z测试字符串是否为空,而一元操作符-n或不加操作符则当字符串为非空时返回真值。

[Note] Note
注意:<>这两个符号同时也是用来做 shell 重定向,所以你必须通过\<\>对其转义。Example 3.2, “一些字符串 tests”给出了更多的字符测的例子。检验一下是不是你所期望样子。

Example 3.2. 一些字符串 tests

[user@domain ~]$ test "abc" = "def" ; echo $?
1
[user@domain ~]$ [ "abc" != "def" ];echo $?
0
[user@domain ~]$ [ "abc" \< "def" ];echo $?
0
[user@domain ~]$ [ "abc" \> "def" ];echo $?
1
[user@domain ~]$ [ "abc" \< "abc" ];echo $?
1
[user@domain ~]$ [ "abc" \> "abc" ];echo $?
1

下面列出一些更常用的文件测试,如果测试一个文件存在且包匹配指定的特性则返回的结果为真。

操作符   属性
-d      Directory
-e      Exists (also -a)
-f      Regular file
-h      Symbolic link (also -L)
-p      Named pipe
-r      Readable by you
-s      Not empty
-S      Socket
-w      Writable by you
-N      Has been modified since last being read

除了上面的一元测试以外,你也可以通过一对操作符来对两个文件进行比较,如下表测试两个文件。

操作符号  为真的情况
-nt     Test if file1 is newer than file 2. The modification date is used for this and the next comparison.
-ot     Test if file1 is older than file 2.
-ef     Test if file1 is a hard link to file2.

一些其它的测试还能检查其它信息如文件的权限。想了解更多内容请使用 help test 来查看 man 手册中 shell 内建命令 test 的小节。你也可以使用 help 命令来查看其它的 shell 内建命令。

-o这个操作符能让我们测试那些可以通过set-o option来设定的各种 shell 选项,如果对应的选项设置了就返回真(1),否则返回假(0),请看Example 3.3, “测试 shell 选项”.

Example 3.3. 测试 shell 选项

[user@domain ~]$ set +o nounset
[user@domain ~]$ [ -o nounset ];echo $?
1
[user@domain ~]$ set -u
[user@domain ~]$ test  -o nounset; echo $?
0

最后,-a-o选项分别表示通过逻辑的与(AND)和(OR)把表达式连接起来,一元操作符-a则是用来反转一个测试的真值。你甚于可以用括号把表达式分组来改变默认的优先级。要谨记,一般情况下,shell 环境会把括号中的表达式放到子 shell 中去运行,所以你需要通过\(\)或者把它俩放到单引号或双引号中来对其进行转义。Example 3.4, “连接和分组tests”演示了对一个表达式德摩根定律的应用。

Example 3.4. 连接和分组tests

[user@domain ~]$ test "a" != "$HOME" -a 3 -ge 4 ; echo $?
1
[user@domain ~]$ [ ! \( "a" = "$HOME" -o 3 -lt 4 \) ]; echo $?
1
[user@domain ~]$ [ ! \( "a" = "$HOME" -o '(' 3 -lt 4 ')' ")" ]; echo $?
1