linux shell 编程:case模式匹配语句 作者:马育民 • 2026-10-08 11:16 • 阅读:10000 # 介绍 `case` 是 bash/sh 脚本里的**多分支条件语句**,用来匹配字符串,等价于其他语言的 `switch`。 # 语法格式 ```bash case 变量 in 模式1) 命令 ;; 模式2|模式3) 命令 ;; *) 默认命令 ;; esac ``` ### 关键字 `in`、`)`、`;;`、`*`、`esac`(case反过来写,表示结束) # 规则 1. **匹配顺序从上到下**,匹配成功就执行对应代码块,**执行完`;;`直接跳出case**,不会继续向下匹配。 2. 模式支持**通配符**: - `*`:匹配任意任意长度任意字符(类似正则 `.*`) - `?`:匹配单个任意字符 - `[abc]`:匹配a/b/c其中一个字符 3. `|` 用来**多个模式或**,`模式1|模式2)`,满足任意一个就命中。 4. `;;` 必须写,代表**分支结束**;少写会继续往下执行下一个分支(穿透)。 5. `*)` 放最后,**所有都不匹配时执行**,相当于 default,可选。 ### 例子:匹配数字 ```bash #!/bin/bash echo "菜单" echo "1. 启动" echo "2. 停止" echo "3. 重启" echo "4. 状态" # 定义option变量,读取用户的输入内容,赋值给option read -p "请输入操作编号: " option echo "测试option的值:$option" case $option in 1) echo "模拟启动服务" ;; 2) echo "模拟停止服务" ;; 3) echo "模拟重启服务" ;; 4) echo "模拟查看服务状态" ;; *) echo "输入无效,请重新输入!" esac echo "脚本执行结束" ``` ### 例子:匹配字符串 很多shell脚本用case解析启动参数: ```bash #!/bin/bash case "$1" in start) echo "启动服务" ;; stop) echo "停止服务" ;; restart) echo "重启服务" ;; help|--help|-h) echo "帮助文档" ;; *) echo "用法: $0 start|stop|restart|help" exit 1 ;; esac ``` **提示:**`"$1"` 加双引号,防止变量为空、含空格导致语法报错。 # 通配符 **重点:**`case` 使用的是 **Shell Glob(文件名通配符),不是正则表达式**! 只支持 glob,不识别 `^ $ . + ()` 这类正则元字符。 ### 支持的 3 个基础 glob 符号 | 符号 | 含义 | 说明 | |------|------|------| | `*` | 匹配**任意长度任意字符**(包括空字符串) | 匹配0个或多个字符 | | `?` | 匹配**单个任意字符** | 必须有1个字符,不能为空 | | `[字符集]` | 匹配**括号内任意单个字符** | 只匹配1个字符 | **语法模板:** ```bash case "$var" in 模式) 命令 ;; esac ``` --- ### 逐个详解 + case 示例 #### 1. `*` 任意字符(0或多个) - `*.log`:以 `.log` 结尾的字符串 - `test*`:以 `test` 开头 - `*error*`:包含 error - `*`:匹配**所有内容**,一般放在最后做默认分支 ```bash file="app.log" case "$file" in *.log) echo "日志文件" ;; test*) echo "以test开头" ;; *error*) echo "包含error关键字" ;; *) echo "其他文件" ;; esac ``` #### 2. `?` 单个任意字符(必须存在1个字符) `?` 代表**恰好 1 位字符,不能为空** - `file?`:file后面跟1个字符,`file1`、`fileA` 匹配;`file`、`file12` 不匹配 - `???.txt`:3个字符 + .txt,如 `abc.txt` ```bash name="app1" case "$name" in app?) echo "app后面跟1个字符" ;; esac ``` > app → 不匹配;app1 ✔;app11 ❌ #### 3. `[]` 字符集合,匹配**单个字符** 格式 `[abc]`、`[0-9]`、`[a-z]`、`[A-Z]` - `[0-9]`:单个数字 0~9 - `[a-z]`:小写英文字母 - `[A-Z]`:大写英文字母 - `[xy]`:只能是 x 或者 y - `[!0-9]`:**取反**,匹配任意一个不是数字的字符(部分shell也可用 `[^0-9]`,推荐 `[!]` POSIX标准) ```bash read -p "输入单个字符:" c case "$c" in [0-9]) echo "是数字" ;; [a-z]) echo "小写字母" ;; [A-Z]) echo "大写字母" ;; [!0-9a-zA-Z]) echo "特殊符号" ;; esac ``` > ⚠️ 注意:`[]` **只匹配1个字符**,不能匹配一串。 > `[0-9][0-9]` 才是两个数字。 --- ### 组合使用示例 ```bash str="a5" case "$str" in [a-z][0-9]) echo "1个小写字母 + 1个数字" ;; esac ``` `a5` ✔;`aa` ❌;`a55` ❌ # 多模式匹配 `模式1|模式2`,满足任意一个就匹配 ```bash case "$opt" in start|restart) echo "启动或重启" ;; *.jpg|*.png|*.gif) echo "图片文件" ;; esac ``` ### 误区 ##### ❌ 误区1:case里面写正则 case **不支持正则**! - 不能用 `^` 开头锚定、`$`结尾锚定、`.`代表任意字符、`+`多次匹配 ```bash # 错误写法!case不识别 ^ case "$var" in ^test) echo 匹配 ;; esac ``` > 想要正则匹配:改用 `if [[ $var =~ 正则 ]]` ##### ❌ 误区2:`*` 匹配换行 case 是字符串比较,变量默认按单行处理,一般不匹配换行。 ##### ❌ 误区3:`[0-9]` 匹配多个数字 `[0-9]` 只匹配**一个数字**。 匹配1~多位数字:case原生glob做不到,要用: ```bash if [[ $num =~ ^[0-9]+$ ]];then echo 纯数字 fi ``` ##### ❌ 误区4:变量不加双引号 `"$var"` 如果变量值包含空格、特殊字符,不加引号会分词破坏匹配。**case里变量建议永远双引号包裹**。 ### glob 转义 如果想**把 `* ? [` 当成普通字符**,需要转义: `\*`、`\?`、`\[` ```bash s="a*b" case "$s" in a\*b) echo "字符串是a*b" ;; esac ``` # case 和 if 的区别 - `case`:**字符串模式匹配**,适合多值枚举、文件名、参数判断,代码清爽;只能做等值/通配匹配,**不能直接比较大小**(不能写 `$a -gt 10`) - `if`:适合**逻辑运算、数值比较、复杂条件**,`&& ||` 组合更灵活 如果要在case里做数值大小判断,可以配合 `(( ))` 或命令返回值: ```bash read n case 1 in $(( n > 10 )) ) echo "大于10" ;; esac ``` # 常见坑 1. 漏写 `;;` → 分支穿透,多个分支一起执行 2. 模式后少写右括号 `)` → 语法报错 3. 变量不加引号,变量带空格时解析异常 4. 把正则写进case模式:**case不是正则!是shell glob通配符**,不能直接用 `.*`、`^`、`$`,这点很容易踩坑。 > 如果要用正则匹配,改用 `if [[ $var =~ 正则 ]]` 原文出处:/show_1GW4Bn7P8KMR.html