shell case(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在 Shell 脚本编程中,条件判断是程序逻辑的核心之一。无论是简单的数值比较,还是复杂的字符串匹配,开发者都需要一种高效且直观的语法结构来实现分支控制。此时,case
语句便成为了一个强大而灵活的工具。对于编程初学者而言,理解 case
的工作原理和使用场景,不仅能提升脚本的可读性,还能显著减少代码冗余。而对于中级开发者,掌握其高级技巧则能进一步优化复杂逻辑的实现。
本文将从基础语法讲起,通过实际案例和代码示例,逐步解析 case
在 Shell 脚本中的核心作用。通过类比日常生活中的常见场景,帮助读者建立对 case
语句的直观认知,最终实现从理论到实践的无缝衔接。
语法基础:Case 语句的结构与核心逻辑
基本结构与关键字
case
语句的语法结构如下:
case VALUE in
PATTERN1)
# 当 VALUE 匹配 PATTERN1 时执行的代码块
;;
PATTERN2)
# 当匹配 PATTERN2 时执行的代码块
;;
*)
# 默认情况(当所有模式均不匹配时触发)
;;
esac
其中:
VALUE
是需要匹配的变量或表达式PATTERN
是模式规则,支持通配符和正则表达式;;
表示模式分支的结束esac
是case
的反向闭合关键字(相当于end case
)
形象比喻:可以把 case
理解为一个“多车道收费站”,每个 PATTERN
是不同车道的通行条件,当输入值(VALUE)符合条件时,车辆(程序执行流)就会驶入对应的车道(代码分支)。
与 If-Else 的对比
虽然 case
和 if-else
都能实现条件判断,但两者在适用场景上有显著区别:
| 特性 | Case 语句 | If-Else 语句 |
|---------------------|-----------------------------------|---------------------------------------|
| 适用场景 | 多个固定模式匹配(如菜单选项、状态码) | 复杂条件组合(如区间判断、布尔运算) |
| 代码简洁性 | 更简洁(尤其当分支超过3个时) | 分支过多时代码易膨胀 |
| 性能表现 | 内部优化更高效(单次匹配) | 需逐个条件判断,复杂度可能呈线性增长 |
| 模式匹配能力 | 支持通配符(如 *
)和正则表达式 | 仅支持布尔表达式 |
核心知识点详解:从基础到进阶
第一步:简单的数值匹配
案例场景:根据用户输入的数字执行不同操作(如计算器模式选择)。
#!/bin/bash
echo "请输入 1-3 的数字选择操作:"
read choice
case $choice in
1)
echo "您选择了加法运算"
;;
2)
echo "您选择了减法运算"
;;
3)
echo "您选择了乘法运算"
;;
*)
echo "输入无效,请输入 1-3 之间的数字"
;;
esac
关键点说明:
- 变量
$choice
需要通过read
命令获取用户输入 - 每个分支的
;;
必须存在,否则会触发“fallthrough”(即执行完当前分支后继续后续分支)
第二步:字符串模式匹配
案例场景:创建一个简单的菜单系统,根据用户输入的命令执行不同功能。
#!/bin/bash
echo "请选择操作:add/delete/list/exit"
read command
case $command in
add)
echo "正在添加数据..."
;;
delete)
echo "正在删除数据..."
;;
list)
echo "正在列出数据..."
;;
exit)
echo "正在退出系统..."
exit 0
;;
*)
echo "未知命令,请重新输入"
;;
esac
关键技巧:
- 字符串匹配默认区分大小写,若需忽略大小写,可在
case
后添加*
修饰符:case "$command" in [Aa][Dd][D] ) ... ;; # 匹配 ADD、Add、add 等变体 esac
第三步:通配符与正则表达式
case
支持以下特殊符号增强匹配能力:
*
:匹配任意长度的任意字符(包括空字符串)?
:匹配单个字符[ ]
:字符集合(如[0-9]
匹配数字)[[...]]
:扩展正则表达式(需配合[[
条件判断)
案例:数字范围匹配
case $number in
[1-5]) echo "输入数字在 1-5 范围内" ;;
[6-9]) echo "输入数字在 6-9 范围内" ;;
10) echo "输入数字是 10" ;;
*) echo "输入超出范围" ;;
esac
进阶案例:邮箱地址验证
case $email in
*[!@].*|*@*.*)
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "邮箱格式正确"
else
echo "邮箱格式错误"
fi
;;
*)
echo "无效输入"
;;
esac
第四步:嵌套 Case 结构
当逻辑分支需要进一步细分时,可以嵌套 case
语句实现多级判断。
案例:文件类型判断
case $file_type in
"image")
case $extension in
"jpg"|"jpeg")
echo "JPEG 图片"
;;
"png")
echo "PNG 图片"
;;
*)
echo "未知图片格式"
;;
esac
;;
"video")
echo "视频文件"
;;
*)
echo "其他类型文件"
;;
esac
高级技巧与最佳实践
1. 默认分支的优雅设计
在 *)
分支中,建议添加 exit
或 break
避免无限循环:
case $status in
success)
echo "操作成功"
;;
error)
echo "发生错误"
;;
*)
echo "未知状态:$status"
exit 1
;;
esac
2. 通配符的组合使用
通过组合 *
和 [ ]
可以实现更精准的匹配:
case $input in
"start_""[0-9]*")
echo "检测到以 'start_' 开头的数字序列"
;;
"end""*")
echo "检测到以 'end' 结尾的字符串"
;;
esac
3. 与函数的结合使用
将 case
结构封装为函数,提升代码复用性:
handle_command() {
case $1 in
"run")
start_process
;;
"stop")
terminate_process
;;
*)
show_usage
;;
esac
}
实战案例:构建一个交互式 Shell 工具
需求:创建一个可交互的系统信息查询工具,支持以下功能:
- 查看 CPU 使用率
- 查看内存信息
- 查看磁盘空间
- 退出程序
完整代码示例:
#!/bin/bash
show_menu() {
echo "1. 查看 CPU 使用率"
echo "2. 查看内存信息"
echo "3. 查看磁盘空间"
echo "4. 退出"
}
loop() {
while true; do
show_menu
read -p "请输入选项(1-4): " choice
case $choice in
1)
top -b -n1 | grep "Cpu(s)"
;;
2)
free -h
;;
3)
df -h
;;
4)
echo "正在退出..."
exit 0
;;
*)
echo "无效选项,请重新输入"
;;
esac
done
}
loop
运行效果:
1. 查看 CPU 使用率
2. 查看内存信息
3. 查看磁盘空间
4. 退出
请输入选项(1-4): 2
total used free shared buff/cache available
Mem: 7.7G 1.2G 4.3G 105M 2.2G 6.1G
Swap: 2.0G 0B 2.0G
总结:Shell Case 的应用场景与价值
通过本文的学习,我们系统掌握了 case
语句从基础语法到高级应用的完整知识体系。总结其核心价值:
- 代码简洁性:用更少的代码实现多分支逻辑判断
- 可维护性:清晰的模式匹配结构便于后期扩展
- 性能优势:单次匹配机制优于多次
if-else
判断
对于编程初学者,建议从简单案例入手,逐步尝试字符串匹配和通配符组合;中级开发者则可探索与函数、正则表达式的深度结合。通过持续实践,case
必将成为 Shell 脚本开发中不可或缺的利器。
延伸思考:在实际项目中,如何将
case
语句与select
命令结合,创建更复杂的交互界面?又该如何利用 Shell 的扩展语法(如[[
)进一步增强模式匹配能力?这些问题的探索将帮助开发者达到更高层次的 Shell 编程水平。