第 36 课 - case 多分支选择
课程:Linux 系统管理与运维 模块:Shell 基础 难度:beginner 标签:case, switch 上一课:if 条件判断 下一课:for 与 while 循环
1. 学习目标
通过本课学习,你将能够:
- 理解
case语句的基本语法和工作原理 - 使用
case语句根据变量的不同值执行不同的命令块 - 掌握
case语句中通配符(如*、?、[...])的使用 - 对比
case和if-elif-else在多分支选择中的优劣 - 在 Shell 脚本中应用
case语句处理实际运维任务
2. 核心概念
什么是 case 语句?
case 语句是 Shell 中用于多分支选择的控制结构,类似于其他编程语言中的 switch 语句。它能够根据一个变量的值,匹配多个可能的模式,并执行对应的命令。
想象一下:你面前有三条路,根据你的目的地(变量值)选择其中一条(执行对应的命令块)。这就是 case 语句的核心思想。
基本语法结构
case $变量 in
模式1)
命令块1
;; # 双分号表示分支结束
模式2)
命令块2
;;
模式3)
命令块3
;;
*) # 默认分支(类似于 else)
默认命令块
;;
esac # 结束标志
关键要素:
- 变量:被检查的值(通常是
$变量) - 模式:用
)结尾,可以使用通配符 - 命令块:匹配成功时执行的命令
- 双分号
;;:标记每个分支的结束 *):默认分支,匹配所有未明确列出的模式esac:case的反写,标记整个结构的结束
3. 代码示例
示例 1:基本 case 语句
#!/bin/bash
# 询问用户想查看什么系统信息
echo "请选择要查看的系统信息:"
echo "1) 主机名"
echo "2) IP 地址"
echo "3) 系统版本"
echo "4) 磁盘使用情况"
read -p "请输入选项 (1-4): " choice
case $choice in
1)
echo "主机名: $(hostname)"
;;
2)
echo "IP 地址: $(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}')"
;;
3)
echo "系统版本: $(cat /etc/os-release | head -n 1)"
;;
4)
echo "磁盘使用情况:"
df -h
;;
*)
echo "错误: 无效选项,请输入 1-4"
;;
esac
示例 2:使用通配符匹配
#!/bin/bash
# 根据文件扩展名判断文件类型
file_name="report.txt"
case $file_name in
*.txt|*.log) # 匹配 .txt 或 .log 文件
echo "文本文件: $file_name"
;;
*.jpg|*.png|*.gif) # 匹配图片文件
echo "图片文件: $file_name"
;;
*.sh) # 匹配 Shell 脚本
echo "Shell 脚本: $file_name"
;;
*.tar|*.gz|*.zip) # 匹配压缩文件
echo "压缩文件: $file_name"
;;
*) # 默认情况
echo "未知文件类型: $file_name"
;;
esac
示例 3:实际运维应用 - 服务管理脚本
#!/bin/bash
service_name="nginx"
case $1 in # $1 是脚本的第一个参数
start)
echo "启动 $service_name 服务..."
sudo systemctl start $service_name
;;
stop)
echo "停止 $service_name 服务..."
sudo systemctl stop $service_name
;;
restart)
echo "重启 $service_name 服务..."
sudo systemctl restart $service_name
;;
status)
echo "查看 $service_name 服务状态:"
sudo systemctl status $service_name
;;
reload)
echo "重新加载 $service_name 配置..."
sudo systemctl reload $service_name
;;
*)
echo "用法: $0 {start|stop|restart|status|reload}"
exit 1
;;
esac
4. 实践练习
练习 1:基础 case 语句
要求:编写一个脚本,根据用户输入的星期几(1-7),输出对应的英文名称和活动安排(1-Monday 学习, 2-Tuesday 运动...)。
预期输出示例:
请输入星期几 (1-7): 3
星期三:Wednesday - 开会日
练习 2:通配符匹配
要求:编写一个脚本,接受一个文件名作为参数,根据文件扩展名输出对应的 MIME 类型(如 .jpg → image/jpeg, .pdf → application/pdf)。
预期输出示例:
./script.sh document.pdf
PDF 文件: application/pdf
练习 3:实际应用 - 自动备份脚本
要求:编写一个备份管理脚本,支持以下操作:
daily:执行每日备份weekly:执行每周备份monthly:执行每月备份clean:清理 30 天前的备份list:列出所有备份文件
预期功能:
./backup.sh daily
执行每日备份...
备份文件: backup_2023-10-15_daily.tar.gz
5. 常见错误
错误 1:忘记双分号 ;;
# 错误写法
case $var in
pattern)
commands
# 缺少 ;;
next_pattern)
commands
;;
esac
错误 2:模式匹配不精确
# 问题:会匹配以 "start" 开头的任何内容
case $action in
start) # 这也会匹配 "starting"、"start service" 等
echo "Starting..."
;;
esac
# 解决方案:使用精确匹配
case $action in
start) # 仅匹配 "start"
echo "Starting..."
;;
esac
错误 3:模式中使用了错误的通配符
# 错误:模式中使用了变量,但没加引号
pattern="*.txt"
case $file in
$pattern) # 可能不会按预期工作
echo "Text file"
;;
esac
# 正确:直接使用通配符模式
case $file in
*.txt)
echo "Text file"
;;
esac
错误 4:忘记 esac 结束
# 错误:缺少 esac
case $var in
pattern)
commands
;;
# 缺少 esac
echo "This will cause syntax error"
错误 5:模式中使用了不支持的正则表达式
# 错误:case 不支持标准正则表达式
case $string in
[0-9]+\.[0-9]+) # 这不是标准 case 模式语法
echo "Decimal number"
;;
esac
# 正确:使用支持的通配符
case $string in
[0-9].[0-9]) # 只匹配单个数字
echo "Single digit decimal"
;;
esac
6. 小结
关键要点回顾:
-
case语句是 Shell 中处理多分支选择的强大工具,语法清晰,易于阅读。 -
基本结构:
- 以
case $variable in开始 - 以
esac结束(case 的反写) - 每个模式以
)结尾 - 用双分号
;;分隔不同分支
- 以
-
模式匹配:
- 支持通配符:
*(任意字符)、?(单个字符)、[...](字符类) - 可以用
|分隔多个模式(如pattern1|pattern2) *)作为默认分支,匹配所有未匹配的模式
- 支持通配符:
-
最佳实践:
- 对于简单的值比较,
case通常比if-elif-else更简洁 - 对于复杂的条件判断(如范围判断、数值比较),
if-elif-else更灵活 - 总是包含默认分支
*)以处理意外输入
- 对于简单的值比较,
-
实际应用:
- 菜单驱动脚本
- 根据文件类型进行不同处理
- 服务管理脚本(start/stop/restart)
- 命令参数解析
下一步学习建议:
- 尝试将之前的
if-elif-else脚本改写为case版本 - 结合
case和函数创建更模块化的脚本 - 学习在
case中使用正则表达式的技巧(通过其他命令实现)
预告:下一课我们将学习 Shell 中的循环结构,包括 for 循环和 while 循环,这是自动化批量处理任务的关键技术。
练习编辑器
rust
Loading...