当前位置: 首页 > java >正文

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 f2f1 比 f2 更新(按修改时间)[ file1.txt -nt file2.txt ] 检查 file1 是否比 file2 新
实验:文件判断实战

实验流程

  1. 创建一个测试目录 /tmp/test_dir
  2. 测试该目录是否存在
  3. 删除目录后,测试是否不存在并重新创建
  4. 测试文件的读写权限

步骤细化

# 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. 测试未赋值的变量是否为空
  2. 给变量赋值后,测试是否非空
  3. 比较两个字符串是否相等

步骤细化

# 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<=
实验:整数比较实战

实验流程

  1. 定义两个整数变量 a=5b=10
  2. 用不同语法测试 a 是否小于 ba 是否不等于 b
  3. 测试 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``
非(取反)!!
实验:逻辑操作符实战

实验流程

  1. 测试 “文件存在且可读”
  2. 测试 “数字小于 20 或大于 1”
  3. 测试 “非(数字等于 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>只支持> <
字符串比较= !== !== != 支持正则== !=
通配符 / 正则不支持不支持支持不支持

如涉及版权问题,请联系作者处理!!!!

http://www.xdnf.cn/news/18635.html

相关文章:

  • 国家自然科学基金(国自然基金)申请技巧详解
  • 深度学习入门:神经网络
  • 【2025CVPR-目标检测方向】UniMamba:基于激光雷达的3D目标检测,采用分组高效曼巴语进行统一空间信道表示学习
  • Q/DR/CX7.2-2020 是中国企业标准体系中
  • 一个备份、去除、新增k8s的node标签脚本
  • `strdup` 字符串复制函数
  • 【JVM内存结构系列】二、线程私有区域详解:程序计数器、虚拟机栈、本地方法栈——搞懂栈溢出与线程隔离
  • 奇怪的前端面试题
  • 智能系统与未来生态演进初步思考
  • LangChain4j中集成Redis向量数据库实现Rag
  • 2-4.Python 编码基础 - 流程控制(判断语句、循环语句、break 语句与 continue 语句)
  • 【Python】新手入门:Python标准库有哪些常用模块?
  • 容器安全实践(二):实践篇 - 从 `Dockerfile` 到 Pod 的权限深耕
  • 美食菜谱数据集(13943条)收集 | 智能体知识库 | AI大模型训练
  • 自学嵌入式第二十六天:数据结构-哈希表、内核链表
  • 从0开始学习Java+AI知识点总结-23.web实战案例(班级和学生增删改查、信息统计)
  • 【Prometheus】Prometheus监控Docker实战
  • C++编程语言:标准库:第36章——字符串类(Bjarne Stroustrup)
  • 【C语言16天强化训练】从基础入门到进阶:Day 8
  • Krea Video:Krea AI推出的AI视频生成工具
  • 知识蒸馏 Knowledge Distillation 序列的联合概率 分解成 基于历史的条件概率的连乘序列
  • 大模型——深度评测智能体平台Coze Studio
  • 2025-08-23 李沐深度学习19——长短期记忆网络LSTM
  • Kafka Streams vs Apache Flink vs Apache Storm: 实时流处理方案对比与选型建议
  • SpringBootWeb入门
  • Ollama 本地部署 Qwen2.5-7b
  • 搜索--常见面试问题
  • Android 之wifi连接流程
  • 使用 LangChain 和 Neo4j 构建知识图谱
  • 一文学会vue的动态权限控制