Shell case ... esac

《Shell case ... esac 分支语句》深度学习版 🧠

🎉 欢迎来到 Shell 编程中非常实用的一章 —— case 分支结构。它是 if 的一种更简洁、清晰的替代方式,特别适合处理多个固定值匹配的情况(如用户输入、命令参数、状态码等)。掌握它,你就能写出更加优雅、可读性强的脚本!


🎯 学习目标

  • 理解 case ... esac 的基本语法与执行流程
  • 掌握如何用 case 实现多条件分支判断
  • 能在实际脚本中灵活使用通配符、正则匹配、模式匹配等技巧
  • 学会结合命令行参数解析、菜单选择等常见应用场景
  • 避免常见陷阱和语法错误,写出健壮可靠的 Shell 条件分支语句

⭐ 核心重点(知识点速览)

类型 内容 描述
基本语法 case value in pattern) ... ;; esac 多分支匹配结构
匹配方式 字符串、通配符、正则 支持 *, ?, [0-9]
结束关键字 ;; 每个分支必须以 ;; 结尾
默认分支 *) 类似 switch 中的 default
常见用途 参数解析、菜单系统、状态处理 提高代码可读性
不同 shell 差异 bash vs dash 注意兼容性问题

📖 详细讲解


一、基本语法结构

case $variable in
    pattern1)
        # 匹配 pattern1 时执行的代码
        ;;
    pattern2)
        # 匹配 pattern2 时执行的代码
        ;;
    *)
        # 默认情况下的代码
        ;;
esac

💡 esaccase 的反向拼写,表示结束。


二、简单示例:根据用户输入执行不同操作 ✅

read -p "请输入你的操作系统(windows/linux/mac):" os

case "$os" in
    windows)
        echo "👋 欢迎 Windows 用户!"
        ;;
    linux)
        echo "🐧 欢迎 Linux 用户!"
        ;;
    mac)
        echo "🍎 欢迎 macOS 用户!"
        ;;
    *)
        echo "❌ 输入无效,请输入 windows、linux 或 mac"
        ;;
esac

三、通配符匹配(Wildcard Matching)🔍

case 支持使用通配符进行模糊匹配:

通配符 含义
* 匹配任意长度字符串
? 匹配单个字符
[abc] 匹配 a、b 或 c
[a-z] 匹配小写字母
` `

✅ 示例:匹配数字范围或前缀

read -p "请输入一个等级(A/B/C/其他):" grade

case "$grade" in
    A|a)
        echo "🎓 成绩优秀!"
        ;;
    B|b)
        echo "📘 成绩良好"
        ;;
    C|c)
        echo "📝 成绩及格"
        ;;
    *)
        echo "❌ 未知等级"
        ;;
esac

四、结合命令行参数解析 📥

这是 case 最常见的用途之一,用于解析脚本启动时传入的参数。

✅ 示例:创建一个带参数的备份脚本

#!/bin/bash

case "$1" in
    full)
        echo "📦 正在执行全量备份..."
        tar -czf /backup/full_$(date +%Y%m%d).tar.gz /home /etc
        ;;
    daily)
        echo "📅 正在执行每日增量备份..."
        rsync -av /home /backup/daily/
        ;;
    help|--help|-h)
        echo "可用参数:full | daily | help"
        exit 0
        ;;
    *)
        echo "❌ 参数错误!请使用 full、daily 或 help"
        exit 1
        ;;
esac

使用方法:

./backup.sh full
./backup.sh daily
./backup.sh --help

五、构建交互式菜单系统 🧩

case 非常适合用来实现命令行菜单界面。

✅ 示例:主菜单脚本

while true
do
    echo "==== 主菜单 ===="
    echo "1. 创建用户"
    echo "2. 查看服务状态"
    echo "3. 退出"
    read -p "请选择操作(1-3):" choice

    case "$choice" in
        1)
            read -p "请输入用户名:" new_user
            useradd "$new_user" && echo "✅ 用户 $new_user 已创建"
            ;;
        2)
            systemctl status nginx
            ;;
        3)
            echo "👋 正在退出..."
            break
            ;;
        *)
            echo "❌ 无效选择,请重试"
            ;;
    esac
done

六、实战案例分析 🧪

🎯 场景一:日志级别过滤器 📊

log_level="INFO"

case "$log_level" in
    DEBUG)
        echo "[DEBUG] 这是调试信息"
        ;;
    INFO)
        echo "[INFO] 这是一般信息"
        ;;
    WARN)
        echo "[WARN] 这是警告信息"
        ;;
    ERROR)
        echo "[ERROR] 这是错误信息"
        ;;
    *)
        echo "❌ 未知日志级别"
        ;;
esac

🎯 场景二:自动识别文件扩展名并处理 📄

file="/tmp/report.docx"

case "$file" in
    *.txt)
        echo "📄 文本文档"
        ;;
    *.doc|*.docx)
        echo "📘 Word 文档"
        ;;
    *.xls|*.xlsx)
        echo "📊 Excel 表格"
        ;;
    *.pdf)
        echo "📑 PDF 文件"
        ;;
    *)
        echo "📂 未知类型"
        ;;
esac

🎯 场景三:检测系统发行版并执行适配命令 🐧

distro=$(grep ID= /etc/os-release | grep -v VERSION_ID | cut -d= -f2)

case "$distro" in
    ubuntu|debian)
        echo "APT 包管理器"
        sudo apt update
        ;;
    centos|rhel)
        echo "YUM 包管理器"
        sudo yum makecache
        ;;
    fedora)
        echo "DNF 包管理器"
        sudo dnf makecache
        ;;
    arch)
        echo "Pacman 包管理器"
        sudo pacman -Sy
        ;;
    *)
        echo "❌ 无法识别系统发行版"
        ;;
esac

七、不同系统的差异与注意事项 ⚠️

项目 Bash Dash (Ubuntu 默认) zsh
支持 case
支持通配符
支持正则表达式 ❌(需用 [[ ]])
推荐脚本开头 #!/bin/bash #!/bin/sh #!/bin/zsh
注意缩进与空格

📝 小贴士:

  • 在 Ubuntu 中默认 /bin/shdash,虽然支持 case,但不推荐使用高级特性。
  • 使用双引号包裹变量,防止路径含空格出错。
  • 每个 case 分支必须以 ;; 结尾。
  • 可以使用 breakcontinue 控制流程。

⚠️ 常见陷阱 & 解决方案

问题 原因 解决方法
语法错误 缺少 ;;esac 添加正确的结束符号
匹配失败 模式未覆盖所有可能 添加 *) 默认分支
变量未加引号 导致空格或特殊字符解析错误 使用双引号包裹变量
不区分大小写 忽略大小写匹配 使用 `
性能问题 高频率调用外部命令 合理优化逻辑或合并处理

🧠 总结与小贴士

技巧 说明
case 是 Shell 的“智能选择器” 让脚本能快速响应多个固定值
适合处理命令行参数、菜单选项、状态码等 提升代码可维护性
推荐配合 readwhile 使用 构建交互式脚本
使用 *) 处理默认情况 增强容错能力
注意 ;; 不能遗漏 否则会继续执行下一个分支
避免嵌套过深 保持代码清晰易读

📚 推荐练习题(可选)

  1. 编写一个脚本,接收用户输入的月份名称,输出对应的季节(春、夏、秋、冬)。
  2. 写一个脚本,根据不同的文件后缀名执行不同的压缩工具(如 .zip/.tar.gz/.7z)。
  3. 实现一个脚本,模拟计算器功能,接收两个数和运算符(+ - * /),输出结果。
  4. 编写一个脚本,解析命令行参数并根据参数执行不同的操作(start/stop/restart/status)。
  5. 创建一个系统诊断脚本,根据不同的平台执行相应的诊断命令(df/free/top)。

🎯 下一章预告:《Shell 函数 Function》

你已经掌握了如何让脚本“多路分支选择”,下一步我们将学习如何将常用代码块封装成函数,提高复用性和可维护性 —— Shell 函数,让你的脚本更模块化、更专业!

需要我继续为你生成下一章内容吗?😊

posted @ 2025-06-18 22:49  红尘过客2022  阅读(45)  评论(0)    收藏  举报