Linux基础(26)之bash中的条件测试

Linux基础(26)之bash中的条件测试

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

像在 Java 或 C# 的一些编程语言中都有单元测试的支持来让我们测试一段代码的运行结果是否满足我们的期望,而在 bash 中,虽然没有单元测试,但它对一些简单的条件测试提供了支持。
测试命令的格式有如下几种:

test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

中括号中的 EXPRESSION 前后必须有空白字符。

数值测试

test 命令为例测试判断 1>31<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 命令为例测试 namemyname 变量是否为空:

[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==STR2STR1 是否等于 STR2
STR1>STR2STR1 是否大于 STR2,用首个字符对应的 ASCII 码值比较 ;
STR1<STR2STR1 是否小于 STR2,用首个字符对应的 ASCII 码值比较 ;
STR1!=STR2STR1 是否不等于 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 是否已 za 开头,例:

[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:判断 FILE1FILE2 是否指向同一个设备上的相同 inode 号;
  • FILE1 -nt FILE2:判断 FILE1 是否新与 FILE2
  • FILE1 -ot FILE2:判断 FILE1 是否旧于 FILE2

组合测试条件

方式一:

  • COMMAND1 && COMMAND2: 与运算,判断 COMMAND1COMMAND2 是否都为真;
  • COMMAND1 || COMMAND2:或运算,判断 COMMAND1COMMAND2 中是否有一个为真;
  • ! COMMAND:非运算,判断 COMMAND 是否为假;

例:判断是否存在 /etc/passwd 并且不存在 /etc/password 文件。

[root@localhost ~]# test ! -e /etc/password && test -e /etc/passwd
[root@localhost ~]# echo $?
0

方式二:

  • [EXPRESSION1 -a EXPRESSION2]:与运算,判断 EXPRESSION1EXPRESSION2 是否都为真;
  • [EXPRESSION1 -o EX{RESSION2]:或运算,判断 EXPRESSION1EXPRESSION2 中是否有一个为真;
  • [ ! 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 选项。

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/linux-base-26.html

Buy me a cup of coffee ☕.