Shell 脚本条件测试
Shell 脚本条件测试
6.1 条件测试简介
在 Shell 脚本中,我们经常需要做条件判断,根据不同的测试结果执行不同的操作。这就像是在问问题,然后根据“是”或“否”来决定下一步做什么。
执行条件测试后:
- 返回 0 表示“真”(条件成立)
- 返回非0 表示“假”(条件不成立)
条件测试的五种语法格式
- test <表达式>
test
命令后需要加空格再写表达式 - [ <表达式> ] (推荐使用👍)
和test
等效,方括号内两端需要有空格 - [[ <表达式> ]]
功能更强的扩展版本,两端也需要空格 - (( <表达式> ))
主要用于数值计算和比较,两端不需要空格 - 直接使用命令
根据命令执行的成功(返回0)或失败(返回非0)来判断
6.1.1 test 条件测试示例
test
命令用于检查文件类型、比较值等。可以通过 help test
查看所有选项。
示例 1:检查文件是否存在
bash
[azurewhisky@shell ~]$ test -f file && echo true || echo false
- 如果 file 存在(真),输出
true
- 如果 file 不存在(假),输出
false
-f
测试是否为普通文件&&
表示“前一个命令成功就执行下一个”||
表示“前一个命令失败就执行下一个”
也可以分开写:
bash
[azurewhisky@shell ~]$ test -f file && echo true # 存在才输出
[azurewhisky@shell ~]$ test -f file || echo false # 不存在才输出
示例 2:检查变量是否为空
bash
[azurewhisky@shell ~]$ unset string # 删除变量
[azurewhisky@shell ~]$ test -z "$string" && echo null string || echo $string
null string[azurewhisky@shell ~]$ string="hello world"
[azurewhisky@shell ~]$ test -z "$string" && echo null string || echo $string
hello world
-z
判断字符串长度是否为 0(空)- 注意:变量建议用双引号括起来,防止空变量导致语法错误
6.1.2 [] 条件测试示例
[]
和 test
功能完全相同,只是写法不同。
示例:检查文件是否存在
bash
[azurewhisky@shell ~]$ [ -f file ] && echo true || echo false
- 方括号
[ ]
内部两端必须有空格 - 逻辑操作符
&&
和||
两端加空格更清晰(可选但建议)
6.1.3 [[]] 条件测试示例
[[]]
是增强版测试命令,支持更强大的模式匹配。
示例:检查文件是否存在
bash
[azurewhisky@shell ~]$ [[ -f file ]] && echo true || echo false
- 双括号
[[ ]]
内部两端也需要空格
提示:
test
、[]
、[[]]
功能相似,选择一种你喜欢的即可(推荐[]
)。
6.2 文件判断表达式
常用的文件测试选项:
选项 | 全拼 | 说明 |
---|---|---|
-d | directory | 存在且为目录则为真 |
-f | file | 存在且为普通文件则为真 |
-e | exist | 存在则为真(不区分文件或目录) |
-r | read | 存在且可读则为真 |
-s | size | 存在且大小非0则为真 |
-w | write | 存在且可写则为真 |
-x | executable | 存在且可执行则为真 |
-L | link | 存在且为链接文件则为真 |
-nt | newer than | 文件1比文件2新则为真(按修改时间) |
-ot | older than | 文件1比文件2旧则为真(按修改时间) |
示例:
bash
[azurewhisky@shell ~]$ data_path=/tmp/azurewhisky
[azurewhisky@shell ~]$ mkdir ${data_path}
[azurewhisky@shell ~]$ [ -d ${data_path} ] && echo "${data_path} exists"
/tmp/azurewhisky exists[azurewhisky@shell ~]$ rmdir ${data_path}
[azurewhisky@shell ~]$ [ -d ${data_path} ] || echo "${data_path} does not exist"
/tmp/azurewhisky does not exist# 检查是否可读 /etc/shadow(通常需要root权限)
[azurewhisky@shell ~]$ [ -r /etc/shadow ] && cat /etc/shadow || echo "Cannot read shadow file"
Cannot read shadow file# 如果 ~/.bashrc 可写,则追加别名
[azurewhisky@shell ~]$ [ -w ~/.bashrc ] && echo "alias pa='ps axu'" >> ~/.bashrc
[azurewhisky@shell ~]$ tail -1 ~/.bashrc
alias pa='ps axu'
多条命令的条件执行
如果条件成立后要执行多条命令,可以用 {}
组合:
bash
[ 条件 ] && {命令1命令2命令3
}
示例:
bash
[azurewhisky@shell ~]$ [ -w ~/.bashrc ] && {
> echo "alias sa='ssh root@servera'" >> ~/.bashrc
> echo "alias sb='ssh root@serverb'" >> ~/.bashrc
> echo "alias sc='ssh root@serverc'" >> ~/.bashrc
> }[azurewhisky@shell ~]$ tail -3 ~/.bashrc
alias sa='ssh root@servera'
alias sb='ssh root@serverb'
alias sc='ssh root@serverc'# 一行写多条命令(用分号分隔)
[azurewhisky@shell ~]$ [ -r /etc/passwd ] && { echo ha; echo ha; echo ha; }
ha
ha
ha
6.3 字符串判断表达式
常用字符串测试操作符:
表达式 | 说明 |
---|---|
-n "字符串" | 长度不为0则为真(非空) |
-z "字符串" | 长度为0则为真(空) |
"串1" = "串2" | 字符串相等则为真 |
"串1" != "串2" | 字符串不相等则为真 |
重要提示:
- 字符串一定要用双引号括起来,避免空变量导致语法错误
- 比较操作符(如
=
)两端必须有空格
示例 1:检查空字符串
bash
[azurewhisky@shell ~]$ unset string
[azurewhisky@shell ~]$ [ -z "$string" ] && echo "null string" || echo "$string"
null string[azurewhisky@shell ~]$ string="hello world"
[azurewhisky@shell ~]$ [ -z "$string" ] && echo "null string" || echo "$string"
hello world
示例 2:检查非空字符串
bash
[azurewhisky@shell ~]$ unset string
[azurewhisky@shell ~]$ [ -n "$string" ] && echo "$string" || echo "null string"
null string[azurewhisky@shell ~]$ string="hello world"
[azurewhisky@shell ~]$ [ -n "$string" ] && echo "$string" || echo "null string"
hello world
示例 3:字符串比较
bash
[azurewhisky@shell ~]$ string="hi"
[azurewhisky@shell ~]$ [ "$string" = "hi" ] && echo hi
hi
[azurewhisky@shell ~]$ [ "$string" = "ha" ] && echo ha # 无输出[azurewhisky@shell ~]$ [ "$string" != "hi" ] && echo "not hi" # 无输出
[azurewhisky@shell ~]$ [ "$string" != "ha" ] && echo "not ha"
not ha
实际应用案例
查看系统脚本中的条件判断:
bash
[azurewhisky@shell ~]$ sed -n '30,31p' /etc/init.d/network
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 6
6.3.3 [[]] 中的模式匹配 =~
[[ ]]
支持使用 =~
进行正则表达式匹配:
bash
[[ "$str" =~ pattern ]]
重要: =~
右边的模式不要用引号,否则会被当作普通字符串而不是正则表达式。
示例:
bash
# 检查变量是否包含数字
[azurewhisky@shell ~]$ str=123abc
[azurewhisky@shell ~]$ [[ "$str" =~ [0-9]+ ]] && echo "Contains numbers" || echo "No numbers"
Contains numbers[azurewhisky@shell ~]$ str=abcdef
[azurewhisky@shell ~]$ [[ "$str" =~ [0-9]+ ]] && echo "Contains numbers" || echo "No numbers"
No numbers# 检查变量是否全是数字
[azurewhisky@shell ~]$ str=123
[azurewhisky@shell ~]$ [[ "$str" =~ ^[0-9]+$ ]] && echo "All numbers" || echo "Not all numbers"
All numbers# 错误示例:加引号后正则会失效
[azurewhisky@shell ~]$ str=123
[azurewhisky@shell ~]$ [[ "$str" =~ "[0-9]+" ]] && echo true || echo false
false
6.4 整数比较操作符
两种风格的整数比较操作符:
在 [] 和 test 中 | 在 [[]] 和 (()) 中 | 说明 |
---|---|---|
-eq | == 或 = | 等于(equal) |
-ne | != | 不等于(not equal) |
-gt | > | 大于(greater than) |
-ge | >= | 大于等于(greater equal) |
-lt | < | 小于(less than) |
-le | <= | 小于等于(less equal) |
特别注意:
- 在
[]
中使用>
和<
时需要转义(如\>
),否则可能被解释为重定向 - 整数比较时,变量可以不加引号,但加上也不错
示例 1:使用 [] 比较
bash
[azurewhisky@shell ~]$ [ 2 -lt 3 ] && echo true || echo false
true
[azurewhisky@shell ~]$ [ 2 -gt 3 ] && echo true || echo false
false
示例 2:常见错误
bash
# 错误:> 不被转义时实际上是重定向,创建了名为 3 的文件!
[azurewhisky@shell ~]$ [ 2 > 3 ] && echo true
true# 正确:需要转义 >
[azurewhisky@shell ~]$ [ 2 \> 3 ] && echo true || echo false
false
示例 3:使用 [[]] 和 (()) 比较
bash
[azurewhisky@shell ~]$ a=98;b=99
[azurewhisky@shell ~]$ [[ $a = $b ]] && echo true || echo false
false[azurewhisky@shell ~]$ (( a >= b )) && echo true || echo false
false
[azurewhisky@shell ~]$ (( a <= b )) && echo true || echo false
true
小结:
[]
中用-eq
,-ne
等比较整数[[]]
和(())
中用==
,!=
,>
,<
等比较整数- 在
[]
中使用>
和<
需要转义
6.5 逻辑操作符
表达式内的逻辑操作符
在 [] 和 test 中 | 在 [[]] 和 (()) 中 | 说明 | ||
---|---|---|---|---|
-a | && | 与(and) | ||
-o | ` | ` | 或(or) | |
! | ! | 非(not) |
表达式外的逻辑操作符(连接命令)
&&
:左边成功才执行右边||
:左边失败才执行右边
示例:
bash
# 检查文件是否存在且可读
[azurewhisky@shell ~]$ file=/etc/passwd
[azurewhisky@shell ~]$ [ -f "$file" -a -r "$file" ] && head -1 "$file"
root:x:0:0:root:/root:/bin/bash# 使用 && 连接两个测试条件
[azurewhisky@shell ~]$ num=10
[azurewhisky@shell ~]$ [ "$num" -lt 20 -o "$num" -gt 1 ] && echo "$num is between 1 and 20"
10 is between 1 and 20# 使用 ! 取反
[azurewhisky@shell ~]$ [ ! 6 -eq 5 ] && echo "6 != 5"
6 != 5
实际应用案例
bash
# 如果目录不存在则创建
[azurewhisky@shell ~]$ data_path=/tmp/azurewhisky
[azurewhisky@shell ~]$ [ -d "$data_path" ] || mkdir "$data_path"
[azurewhisky@shell ~]$ ls -d "$data_path"
/tmp/azurewhisky
6.6 四种测试方法对比总结
特性说明 | [] | test | [[]] | (()) |
---|---|---|---|---|
边界是否需要空格 | 需要 | 需要 | 需要 | 不需要 |
逻辑操作符 | !、-a、-o | !、-a、-o | !、&&、|| | !、&&、|| |
整数比较 | -eq、-ne、-gt等 | -eq、-ne、-gt等 | -eq、-ne、-gt等 | ==、!=、>、<等 |
字符串比较 | =、==、!= | =、==、!= | =、==、!= | ==、!= |
通配符匹配 | 不支持 | 不支持 | 支持(=~) | 不支持 |
建议:
- 日常使用
[]
足够多数情况- 需要模式匹配时用
[[]]
- 数值计算用
(())
- 保持代码风格一致最重要
希望这份更轻松易懂的笔记能帮助你更好地学习和复习 Shell 条件测试!如有问题,欢迎随时提问。