10.Shell脚本修炼手册---脚本的条件测试与比较
Shell 脚本的条件测试
文章目录
- Shell 脚本的条件测试
- 条件测试是什么?为什么需要它?
- 条件测试的 5 种常用语法
- 语法对比示例:判断数字 2 是否小于 3
- 文件判断:检查文件 / 目录的状态
- 实验:文件判断实战
- 字符串判断:比较文本或变量
- 实验:字符串判断实战
- 进阶:用`[[ ]]`做正则匹配
- 整数比较:比较数字大小
- 实验:整数比较实战
- 逻辑操作符:组合多个条件(巩固)
- 实验:逻辑操作符实战
- 四种语法的核心区别(巩固)
条件测试是什么?为什么需要它?
简单说,条件测试就是 Shell 脚本里的 “判断题”—— 通过测试一个条件是否成立,来决定接下来该执行什么操作。比如:判断一个文件是否存在,再决定是否创建它;判断两个数字的大小,再决定显示什么内容。
在 Shell 中,条件测试的结果用 “返回值” 表示:
- 若条件成立(真),返回值为 0;
- 若条件不成立(假),返回值为 非 0(通常是 1)。
条件测试的 5 种常用语法
我们可以用以下 5 种方式写 “判断题”,它们的核心作用相同,但用法略有区别:
语法格式 | 说明 | 注意事项 |
---|---|---|
test <判断表达式> | 基础测试命令 | test 和表达式之间必须有空格 |
[ <判断表达式> ] | 等价于 test ,推荐使用 | 中括号 [ ] 与表达式之间必须有空格 |
[[ <判断表达式> ]] | 扩展语法,功能更强 | 双中括号 [[ ]] 与表达式之间必须有空格,支持通配符和更多操作符 |
(( <判断表达式> )) | 主要用于整数计算和比较 | 双小括号 (( )) 与表达式之间不需要空格 |
命令 | 直接用命令的返回值作为结果 | 命令执行成功(返回 0)则条件为真,失败则为假 |
语法对比示例:判断数字 2 是否小于 3
# 语法1:test
test 2 -lt 3 && echo "真" || echo "假" # 输出“真”,-lt表示“小于”# 语法2:[](推荐)
[ 2 -lt 3 ] && echo "真" || echo "假" # 输出“真”,注意[和]前后的空格# 语法3:[[]]
[[ 2 -lt 3 ]] && echo "真" || echo "假" # 输出“真”# 语法4:(())
(( 2 < 3 )) && echo "真" || echo "假" # 输出“真”,这里直接用<符号# 语法5:命令(以判断文件是否存在为例)
ls file.txt && echo "文件存在" || echo "文件不存在" # 若file.txt存在,ls执行成功则输出“文件存在”
小贴士:
&&
表示 “如果前面为真,就执行后面”;||
表示 “如果前面为假,就执行后面”,类似 “且” 和 “或” 的逻辑。
文件判断:检查文件 / 目录的状态
我们经常需要判断文件是否存在、是否为目录、是否可读写等,以下是常用的文件测试选项:
选项 | 含义 | 举例 |
---|---|---|
-d 路径 | 路径存在且是目录 | [ -d /tmp ] 检查 /tmp 是否为目录 |
-f 路径 | 路径存在且是普通文件 | [ -f /etc/passwd ] 检查 /etc/passwd 是否为普通文件 |
-e 路径 | 路径存在(不管是文件还是目录) | [ -e ~/test ] 检查当前用户目录下是否有 test(文件或目录) |
-r 路径 | 路径存在且可读 | [ -r /etc/shadow ] 检查是否有权限读 /etc/shadow |
-w 路径 | 路径存在且可写 | [ -w ~/.bashrc ] 检查是否有权限写.bashrc |
-x 路径 | 路径存在且可执行 | [ -x /bin/ls ] 检查 ls 命令是否可执行 |
-s 路径 | 路径存在且大小不为 0 | [ -s file.txt ] 检查 file.txt 是否非空 |
f1 -nt f2 | f1 比 f2 更新(按修改时间) | [ file1.txt -nt file2.txt ] 检查 file1 是否比 file2 新 |
实验:文件判断实战
实验流程:
- 创建一个测试目录
/tmp/test_dir
- 测试该目录是否存在
- 删除目录后,测试是否不存在并重新创建
- 测试文件的读写权限
步骤细化:
# 1. 定义测试目录路径
test_dir="/tmp/test_dir"# 2. 测试目录是否存在:若存在则输出提示
[ -d "$test_dir" ] && echo "目录 $test_dir 已存在" # 首次执行时目录不存在,无输出# 3. 创建目录后再次测试
mkdir "$test_dir" # 创建目录
[ -d "$test_dir" ] && echo "目录 $test_dir 已存在" # 输出“目录 /tmp/test_dir 已存在”# 4. 删除目录后,测试是否不存在并重新创建
rmdir "$test_dir" # 删除目录
[ -d "$test_dir" ] || mkdir "$test_dir" # 若目录不存在则创建,此时会重新创建目录
ls -d "$test_dir" # 验证目录已重建,输出“/tmp/test_dir”# 5. 测试文件读写权限(以/etc/passwd和/etc/shadow为例)
[ -r "/etc/passwd" ] && echo "可以读取/etc/passwd" # 普通用户通常可读取,输出提示
[ -r "/etc/shadow" ] && echo "可以读取/etc/shadow" || echo "无法读取/etc/shadow" # 普通用户无权限,输出“无法读取”
字符串判断:比较文本或变量
字符串测试用于检查变量是否为空、两个字符串是否相等,常用选项如下:
选项 | 含义 | 举例 |
---|---|---|
-z "字符串" | 字符串长度为 0(空字符串) | [ -z "$name" ] 检查 name 变量是否为空 |
-n "字符串" | 字符串长度不为 0(非空) | [ -n "$name" ] 检查 name 变量是否非空 |
"串1" = "串2" | 两个字符串相等(== 也可) | [ "$a" = "$b" ] 检查 a 和 b 是否相等 |
"串1" != "串2" | 两个字符串不相等 | [ "$a" != "$b" ] 检查 a 和 b 是否不等 |
实验:字符串判断实战
实验流程:
- 测试未赋值的变量是否为空
- 给变量赋值后,测试是否非空
- 比较两个字符串是否相等
步骤细化:
# 1. 测试未赋值的变量(空字符串)
unset str # 清除变量str(确保为空)
[ -z "$str" ] && echo "str是空字符串" # 输出“str是空字符串”(-z检测空)
[ -n "$str" ] && echo "str非空" || echo "str是空字符串" # 输出“str是空字符串”(-n检测非空)# 2. 给变量赋值后测试
str="hello" # 给str赋值
[ -z "$str" ] && echo "str是空字符串" || echo "str的值是:$str" # 输出“str的值是:hello”
[ -n "$str" ] && echo "str的值是:$str" # 输出“str的值是:hello”# 3. 比较两个字符串是否相等
str1="hello"
str2="world"
[ "$str1" = "$str2" ] && echo "str1和str2相等" || echo "str1和str2不等" # 输出“不等”str2="hello" # 让str2与str1相等
[ "$str1" != "$str2" ] && echo "str1和str2不等" || echo "str1和str2相等" # 输出“相等”
注意:字符串比较时,变量必须加双引号(如
"$str"
),否则空变量会导致语法错误!
进阶:用[[ ]]
做正则匹配
[[ ]]` 支持用 `=~` 操作符进行正则表达式匹配,语法:`[[ "字符串" =~ 正则模式 ]]
示例:判断字符串是否包含数字
# 测试包含数字的字符串
str="123abc"
[[ "$str" =~ [0-9] ]] && echo "$str 包含数字" || echo "$str 不包含数字" # 输出“包含数字”# 测试不包含数字的字符串
str="abcdef"
[[ "$str" =~ [0-9] ]] && echo "$str 包含数字" || echo "$str 不包含数字" # 输出“不包含数字”# 注意:正则模式不能加引号,否则会被当作普通字符串匹配
[[ "$str" =~ "[0-9]" ]] && echo "匹配成功" || echo "匹配失败" # 输出“匹配失败”(因为"[0-9]"被当作字符串)
整数比较:比较数字大小
整数比较用于判断两个数字的大小关系,不同语法对应的操作符不同,避免用错!
比较关系 | [] 和 test 中使用 | [[]] 和 (()) 中使用 |
---|---|---|
等于 | -eq | == 或 = |
不等于 | -ne | != |
大于 | -gt | > |
小于 | -lt | < |
大于等于 | -ge | >= |
小于等于 | -le | <= |
实验:整数比较实战
实验流程:
- 定义两个整数变量
a=5
、b=10
- 用不同语法测试
a
是否小于b
、a
是否不等于b
- 测试
a
是否大于等于b
步骤细化:
# 1. 定义变量
a=5
b=10# 2. 测试a是否小于b(正确结果:是)
[ $a -lt $b ] && echo "$a < $b" # 输出“5 < 10”([]中用-lt)
[[ $a < $b ]] && echo "$a < $b" # 输出“5 < 10”([[]]中用<)
(( $a < $b )) && echo "$a < $b" # 输出“5 < 10”((())中用<)# 3. 测试a是否不等于b(正确结果:是)
[ $a -ne $b ] && echo "$a != $b" # 输出“5 != 10”([]中用-ne)
[[ $a != $b ]] && echo "$a != $b" # 输出“5 != 10”([[]]中用!=)
(( $a != $b )) && echo "$a != $b" # 输出“5 != 10”((())中用!=)# 4. 测试a是否大于等于b(正确结果:否)
[ $a -ge $b ] && echo "$a >= $b" || echo "$a < $b" # 输出“5 < 10”
[[ $a >= $b ]] && echo "$a >= $b" || echo "$a < $b" # 输出“5 < 10”
(( $a >= $b )) && echo "$a >= $b" || echo "$a < $b" # 输出“5 < 10”
注意:
[]
中不能直接用<
或>
(会被当作字符串比较),必须用-lt
/-gt
等!
逻辑操作符:组合多个条件(巩固)
有时需要同时判断多个条件(比如 “文件存在且可写”),这时需要用逻辑操作符:
逻辑关系 | [] 和 test 中使用 | [[]] 和 (()) 中使用 | ||
---|---|---|---|---|
与(两边都为真才为真) | -a | && | ||
或(一边为真就为真) | -o | ` | ` | |
非(取反) | ! | ! |
实验:逻辑操作符实战
实验流程:
- 测试 “文件存在且可读”
- 测试 “数字小于 20 或大于 1”
- 测试 “非(数字等于 5)”
步骤细化:
# 1. 测试“文件存在且可读”(以/etc/passwd为例)
file="/etc/passwd"
[ -f "$file" -a -r "$file" ] && echo "$file 存在且可读" # []中用-a表示与,输出提示
[[ -f "$file" && -r "$file" ]] && echo "$file 存在且可读" # [[]]中用&&表示与,输出提示# 2. 测试“数字小于20或大于1”(以num=10为例)
num=10
[ $num -lt 20 -o $num -gt 1 ] && echo "$num 在1-20之间" # []中用-o表示或,输出提示
[[ $num -lt 20 || $num -gt 1 ]] && echo "$num 在1-20之间" # [[]]中用||表示或,输出提示# 3. 测试“非(数字等于5)”(以num=10为例)
[ ! $num -eq 5 ] && echo "$num 不等于5" # 用!取反,输出提示
[[ ! $num -eq 5 ]] && echo "$num 不等于5" # 用!取反,输出提示
四种语法的核心区别(巩固)
特性 | [] | test | [[]] | (()) | ||||
---|---|---|---|---|---|---|---|---|
边界空格 | 必须有 | 必须有 | 必须有 | 不需要 | ||||
逻辑操作符 | ! -a -o | ! -a -o | ! && ` | ` | ! && ` | ` | ||
整数比较 | -eq -gt 等 | -eq -gt 等 | 支持-eq 和> 等 | 只支持> < 等 | ||||
字符串比较 | = != | = != | = != 支持正则 | == != | ||||
通配符 / 正则 | 不支持 | 不支持 | 支持 | 不支持 |
如涉及版权问题,请联系作者处理!!!!