像在 Java 或 C# 的一些编程语言中都有单元测试的支持来让我们测试一段代码的运行结果是否满足我们的期望,而在 bash 中,虽然没有单元测试,但它对一些简单的条件测试提供了支持。
测试命令的格式有如下几种:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
中括号中的
EXPRESSION前后必须有空白字符。
数值测试
以 test 命令为例测试判断 1>3 与 1<3 的结果。
[root@localhost ~]# test 1 -gt 3
[root@localhost ~]# echo $?
1
[root@localhost ~]# test 1 -lt 3
[root@localhost ~]# echo $?
0
test命令的方式需使用选项来指定比较运算符类型,如上示例中-gt代指>,-lt代指<。
数值测试时test命令支持的选项如下:
-gt:是否大于;-ge:是否大于等于;-eq:是否等于;-ne:是否不等于;-lt:是否小于;-le:是否小于等于;
以 [ EXPRESSION ] 的方式为例:
[root@localhost ~]# [ 1 -gt 3 ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 1 -lt 3 ]
[root@localhost ~]# echo $?
0
它支持的选项与
test命令相同。
以 [[ EXPRESSION ]] 的方式为例:
[root@localhost ~]# [[ 1 > 3 ]]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [[ 1 < 3 ]]
[root@localhost ~]# echo $?
0
[[ EXPRESSION ]]的方式可直接使用算数运算符进行比较,而不需使用选项,可读性更高。
结果为真时$?的结果为0,为假时$?的结果为1。
字符串测试
以 test 命令为例测试 name 与 myname 变量是否为空:
[root@localhost ~]# name='zze'
[root@localhost ~]# test -z $name
[root@localhost ~]# echo $?
1
[root@localhost ~]# test -z $myname
[root@localhost ~]# echo $?
0
字符串测试时
test命令支持的选项如下:
-z:测试字符串是否为空,空则为真,不空则为假;-n:测试字符串是否不空,不空则为真,空则为假;除了支持上述选项外,还可通过操作符比较,如下:
STR1==STR2:STR1是否等于STR2;
STR1>STR2:STR1是否大于STR2,用首个字符对应的 ASCII 码值比较 ;
STR1<STR2:STR1是否小于STR2,用首个字符对应的 ASCII 码值比较 ;
STR1!=STR2:STR1是否不等于STR2;
STR=~PATTERN:左侧字符串STR能否被右侧的PATTERN所匹配,此表达式一般用于[[ EXPRESSION ]]中;
以 [ EXPRESSION ] 的方式为例:
[root@localhost ~]# name='zze'
[root@localhost ~]# [ -z "$name" ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# echo $myname
[root@localhost ~]# [ -z "$myname" ]
[root@localhost ~]# echo $?
0
以 [[ EXPRESSION ]] 测试变量 name 是否已 z 或 a 开头,例:
[root@localhost ~]# [[ "$name" =~ ^z.* ]]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [[ "$name" =~ ^a.* ]]
[root@localhost ~]# echo $?
1
文件测试
以 test 命令为例分别测试 /etc/passwd 文件和 /etc/password 文件是否存在为例:
[root@localhost ~]# test -a /etc/passwd
[root@localhost ~]# echo $?
0
[root@localhost ~]# test -a /etc/password
[root@localhost ~]# echo $?
1
文件测试相对于数值和字符串测试来说稍显复杂,主要通过不同的选项来做不同的测试,可大致分为以下几类:
存在性测试
-a:判断文件是否存在,存在则为真,不存在则为假;-e:同-a;-s:判断文件是否存在且不为空;
类别测试
-b:判断文件是否为块设备文件;-c:判断文件是否为字符设备文件;-d:判断文件是否是一个目录;-f:判断文件是否只是一个普通文件;-h或-L:判断文件是否是为符号链接文件;-p:判断文件是否为命名管道文件;-S:判断文件是否为套接字文件;
普通权限测试
-r:判断当前用户对该文件是否拥有读权限;-w:判断当前用户对该文件是否拥有写权限;-x:判断当前用户对该文件是否拥有执行权限;
特殊权限测试
-g:判断当前用户对该文件是否拥有sgid权限;-u:判断当前用户对该文件是否拥有suid权限;-k:判断当前用户对该文件是否拥有sticky权限;
文件状态测试
-t:要注意的是使用该选项时参数并不是一个普通文件,而是文件描述符(file descriptor),而该选项的作用就是判断指定文件描述符是否已被打开并与某终端相关联;-N:判断从上一次被读取后至今是否被修改过;-O:判断当前用户是否是该文件的属主;-G:判断当前用户是否在该文件属组中;
在前面其实有提到过,在 linux 中标准输入的文件描述符为
0,标准输出的文件描述符为1,标准错误输出的文件描述符为2,而打开的其它文件都有一个文件描述符与之对应。
以标准输入的文件描述符0为例,测试它是否已被打开并与某终端相关联:[root@localhost ~]# test -t 0 [root@localhost ~]# echo $? 0因为标准输入的来源其实就是键盘,所以在终端使用键盘键入命令的情况下标准输入的文件描述符肯定是为已被打开且与当前终端相关联了的,所以输出的结果为真;
双目测试
FILE1 -ef FILE2:判断FILE1与FILE2是否指向同一个设备上的相同 inode 号;FILE1 -nt FILE2:判断FILE1是否新与FILE2;FILE1 -ot FILE2:判断FILE1是否旧于FILE2;
组合测试条件
方式一:
COMMAND1 && COMMAND2: 与运算,判断COMMAND1和COMMAND2是否都为真;COMMAND1 || COMMAND2:或运算,判断COMMAND1和COMMAND2中是否有一个为真;! COMMAND:非运算,判断COMMAND是否为假;
例:判断是否存在 /etc/passwd 并且不存在 /etc/password 文件。
[root@localhost ~]# test ! -e /etc/password && test -e /etc/passwd
[root@localhost ~]# echo $?
0
方式二:
[EXPRESSION1 -a EXPRESSION2]:与运算,判断EXPRESSION1和EXPRESSION2是否都为真;[EXPRESSION1 -o EX{RESSION2]:或运算,判断EXPRESSION1和EXPRESSION2中是否有一个为真;[ ! EXPRESSION ]:非运算,判断EXPRESSION是否为假;
例:判断是否存在 /etc/passwd 并且不存在 /etc/password 文件。
[root@localhost ~]# [ ! -e /etc/password -a -e /etc/passwd ]
[root@localhost ~]# echo $?
0
同下:
[root@localhost ~]# test ! -e /etc/password -a -e /etc/passwd
[root@localhost ~]# echo $?
0
即可以通过 -a 和 -o 选项来连接两个表达式,而不能使用 && 和 ||。
[ EXPRESSION ]这种方式的使用和test命令相同,test命令有的选项都可以直接在[EXPRESSION]中使用;
而[[ EXPRESSION ]]这种方式与test和[ EXPRESSION ]都不同,它支持原生符号进行比较和运算,如在数值测试中>就表示大于,而不用使用-gt选项,在逻辑运算中&&就表示与运算,而不用使用-a选项。
评论区