linux shell 编程:test条件判断命令

介绍

test 是 shell 内置的条件判断命令,用来做文件、字符串、数值比较;返回退出码:0 代表真,非0 代表假。

语法

test expression

等价写法

[ 条件 ],注意 [ 后面、] 前面必须有空格。

[[ ]] 是 bash 扩展,不是标准 test,后面会区分。

# 两种写法完全等价(POSIX test)
[ expression ]

一、返回值规则

test 1 -gt 0
echo $?   # 0:条件成立
test 1 -lt 0
echo $?   # 1:条件不成立

二、数值比较(只用于整数,不能浮点数)

语法:test 整数1 OP 整数2

参数 含义
-eq equal 等于
-ne not equal 不等于
-gt greater than 大于
-ge greater or equal 大于等于
-lt less than 小于
-le less or equal 小于等于

示例:

a=10
test $a -eq 10
[ $a -gt 5 ] && echo yes

⚠️ 坑:数值比较只能整数;变量为空会报错,建议加引号:[ "$a" -gt 5 ]

三、字符串判断

表达式 说明
-z "$str" 字符串长度为0(空字符串)
-n "$str" 字符串长度非0(不为空)
"$s1" = "$s2" 字符串相等
"$s1" != "$s2" 字符串不等

注意:字符串变量一定要双引号包裹,防止变量为空、带空格导致语法错误!

str=""
test -z "$str" && echo "空字符串"

str="hello"
test -n "$str" && echo "非空"

[ "$user" = "root" ]

⚠️ POSIX test 里字符串比较不能用 ==,== 是 [[ ]] bash扩展。

四、文件测试(高频)

参数 含义
-e file 文件存在(不管类型:普通文件/目录/链接)
-f file 存在且是普通文件
-d file 存在且是目录
-L file 存在且是符号链接
-r file 文件可读
-w file 文件可写
-x file 文件可执行
-s file 文件存在且大小>0(非空文件)
-O file 文件属主是当前用户
-G file 文件属组是当前用户组
-nt file1 -nt file2:file1 更新(newer than)
-ot file1 -ot file2:file1 更旧(older than)

示例:

test -d /etc && echo "/etc 是目录"
[ -f "/etc/passwd" ] && echo "存在普通文件"
[ -s test.log ] || echo "文件为空或不存在"

五、逻辑运算(test 原生,不是 && ||)

test 使用 -a(and)、-o(or),! 取反

⚠️ -a / -o 在部分场景有优先级坑,推荐用多个 test + shell 的 && || 代替

运算符 说明
! expr 取反
expr1 -a expr2 逻辑与,两个都成立
expr1 -o expr2 逻辑或,任意一个成立
# 文件存在 并且 是普通文件
test -e "a.txt" -a -f "a.txt"

# 不是目录
! test -d "/tmp"
[ ! -d "/tmp" ]

推荐更安全写法(分开判断,shell逻辑连接):

[ -e "a.txt" ] && [ -f "a.txt" ]

六、test / [ ] 和 [[ ]] 的区别

  1. test / [ ]:POSIX 标准,所有 shell(sh/bash/dash) 都支持
    • 字符串相等只能 =,不支持 ==
    • 没有正则匹配
    • 变量不引号容易炸
  2. [[ ]]:bash/ksh 扩展,不是标准 test
    • 支持 ==、!= 模式匹配(通配符)
    • 支持 =~ 正则匹配
    • 内部空格处理更友好,不用对变量大量引号转义
      # [[ ]] bash特有,不属于test命令
      [[ "abc123" =~ ^abc ]]
      

七、常见坑

  1. [ 是命令,后面必须空格:[$a -gt 1] 直接报错
  2. 变量务必双引号:[ -z $var ] 当var为空时语法错误,写成 [ -z "$var" ]
  3. -gt/-eq 只能整数;浮点数要用 bc 比较
  4. -a / -o 优先级问题,复杂条件不要用,拆成多个 [] && []
  5. = 是字符串比较,不要拿来比较数字:[ "10" = "2" ] 做字符串比对,不是数值

八、速查表

# 数值
[ $a -eq $b ] 相等
[ $a -ne $b ] 不等
[ $a -gt $b ] >
[ $a -ge $b ] >=
[ $a -lt $b ] <
[ $a -le $b ] <=

# 字符串
[ -z "$s" ] 空串
[ -n "$s" ] 非空串
[ "$s1" = "$s2" ] 相等
[ "$s1" != "$s2" ] 不等

# 文件
[ -e path ] 存在
[ -f path ] 普通文件
[ -d path ] 目录
[ -L path ] 软链接
[ -r path ] 可读
[ -w path ] 可写
[ -x path ] 可执行
[ -s path ] 文件非空

# 逻辑
! [ expr ] 取反
[ e1 ] && [ e2 ] 与
[ e1 ] || [ e2 ] 或