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 是模式规则,支持通配符和正则表达式
  • ;; 表示模式分支的结束
  • esaccase 的反向闭合关键字(相当于 end case

形象比喻:可以把 case 理解为一个“多车道收费站”,每个 PATTERN 是不同车道的通行条件,当输入值(VALUE)符合条件时,车辆(程序执行流)就会驶入对应的车道(代码分支)。

与 If-Else 的对比

虽然 caseif-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. 默认分支的优雅设计

*) 分支中,建议添加 exitbreak 避免无限循环:

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 工具

需求:创建一个可交互的系统信息查询工具,支持以下功能:

  1. 查看 CPU 使用率
  2. 查看内存信息
  3. 查看磁盘空间
  4. 退出程序

完整代码示例

#!/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 语句从基础语法到高级应用的完整知识体系。总结其核心价值:

  1. 代码简洁性:用更少的代码实现多分支逻辑判断
  2. 可维护性:清晰的模式匹配结构便于后期扩展
  3. 性能优势:单次匹配机制优于多次 if-else 判断

对于编程初学者,建议从简单案例入手,逐步尝试字符串匹配和通配符组合;中级开发者则可探索与函数、正则表达式的深度结合。通过持续实践,case 必将成为 Shell 脚本开发中不可或缺的利器。

延伸思考:在实际项目中,如何将 case 语句与 select 命令结合,创建更复杂的交互界面?又该如何利用 Shell 的扩展语法(如 [[)进一步增强模式匹配能力?这些问题的探索将帮助开发者达到更高层次的 Shell 编程水平。

最新发布