Bash : test 命令

在 Bash 脚本中我们一般会使用 test 命令来进行条件检查。test 命令的返回值为 0 或 1。0 表示 true, 1 表示 false。简单起见,我们可以直接认为 test 的结果为 true 或 false。

还可以使用中括号代替 test,需要注意的是括号和表达式之间一定要留有空格,所以下面的两种写法是等同的:

test "$1" = "$name"

[ "$1" = "$name" ]

test 命令的主要用途是检查字符串、比较整数和检查文件的属性。本文将通过简单的示例介绍 test 命令的常见用法。

检查字符串

判断字符串是否为空

test 检查字符串时,非空的字符串返回 true,空字符串或者没有参数都返回 false。

if test "$abc"; then
echo "It's not an empty string."
else
echo "It's an empty string."
fi

运行上面代码的输出结果为:

It's an empty string.

这是因为我们没有定义变量 abc ,所以 "$abc" 被解释成了空字符串。

其实使用检查空字符串的运算符 -n 会让代码具有更清晰的含义:

if test -n "$abc"; then
echo "It's not an empty string."
else
echo "It's an empty string."
fi

-n 的含义为:字符串的长度不为 0 时返回 true。所以这段代码的输出结果和上面一样。

如果我们需要判断一个空的字符串可以直接使用运算符 -z:

if test -z "$abc"; then
echo "It's an empty string."
fi

这段代码输出的结果仍然是:

It's an empty string.

判断字符串相等

test 支持两个运算符来判断字符串相等:= 和 ==。

abc="hello"
if test "hello" == "$abc"; then
echo "You got same string."
fi

运行上面代码的输出结果为:

You got same string.

因为 = 看起来更像是在赋值,所以我更倾向于使用 ==。但是当你的脚本需要跨平台时,最好还是使用 =(test 中的 = 是 POSIX 标准定义的!)。

如果要判断两个字符串不相等,可以使用 != 运算符:

abc="helloo"
if test "hello" != "$abc"; then
echo "Your word is not 'hello'."
fi

运行上面代码的输出结果为:

Your word is not 'hello'.

为什么用双引号把变量包起来?

如果你留意前面的代码会发现我们在引用变量时都用双引号包起来了,这是写 shell 脚本中的一个小技巧。尝试运行下面的代码:

abc="hello xx"
if test "hello" != $abc; then
echo "Your word is not 'hello'."
fi

会提示语法错误:

Bash : test 命令

因为变量 abc 的值为 "hello xx",在字符串中间有个空格。所以在 Bash 进行命令解释的时候,上面的 test 命令变成了:

test "hello" != hello xx

这不是一个合法的 test 命令,所以脚本执行时就报错了!

其实不光是空格,包含在 $IFS 中的其它字符,还有变量为空时,都会造成语法错误。所以使用双引号包裹变量是一种保护机制,可以提高脚本的健壮性。

比较数字(整数)

test 支持整数间的比较操作,可用的运算符有 '-eq','-ne','-lt','-le','-gt','-ge'。
比如判断两个整数相等可以使用 -eq 运算符:

num=
if test "$num" -eq ; then
echo "num is 3."
fi

运行上面代码的输出结果为:

num is .

常见数字运算符的含义分别为:

n1 -eq n2 : 整数 n1 等于 n2
n1 -ne n2 : 整数 n1 不等于 n2
n1 -lt n2 : n1 小于 n2
n1 -gt n2 : n1 大于 n2
n1 -le n2 : n1 小于或等于 n2
n1 -ge n2 : n1 大于或等于 n2

检查文件属性

检查文件的属性也是 test 常见用法。比如要检查一个文件的类型是不是普通文件,可以使用 -f 选项:

touch test.sh
filename="test.sh"
if test -f "$filename"; then
echo "It's a regular file."
fi

运行上面代码的输出结果为:

It's a regular file.

另一个重要的选项是 -d,它用来检查一个路径是不是目录:

dirname="/bin"
if test -d "$dirname"; then
echo "It's a directory."
fi

运行上面代码的输出结果为:

It's a directory.

如果是仅仅判断一个路径是否存在,可以使用 -e 运算符。它仅检查文件是否存在而不关心文件的具体类型。

下面是其它一些常用的文件检查运算符:

-b file : 文件存在并且是块设备文件。
-c file : 文件存在并且是字符设备文件。
-d file : 文件存在并且是一个目录。
-e file : 文件存在。
-f file : 文件存在并且是一般文件。
-g file : 文件存在并且设置了 setgid 位。
-h file : 文件存在并且是一个链接文件。
-p file : 文件存在并且是一个命名管道(FIFO)。
-r file : 文件存在并且是可读的。
-s file : 文件存在并且有内容。
-u file : 文件存在并且设置了 setuid。
-w file : 文件存在并且是可写的。
-x file : 文件存在并且是可执行的。
-S file : 文件存在并且是一个 socket。

总结

个人感觉 test 是 Bash 中很重要的命令。在你掌握了基本的脚本编写技能后,通过 test 命令并结合 if 等流程语句你可以控制程序的执行流程,从而开启脚本编程的大门。

上一篇:“假学习“&”真学习“?(摘)


下一篇:洛谷P1461 海明码 Hamming Codes