介绍
case 是 bash/sh 脚本里的多分支条件语句,用来匹配字符串,等价于其他语言的 switch。
语法格式
case 变量 in
模式1)
命令
;;
模式2|模式3)
命令
;;
*)
默认命令
;;
esac
关键字
in、)、;;、*、esac(case反过来写,表示结束)
规则
- 匹配顺序从上到下,匹配成功就执行对应代码块,执行完
;;直接跳出case,不会继续向下匹配。 - 模式支持通配符:
*:匹配任意任意长度任意字符(类似正则.*)?:匹配单个任意字符[abc]:匹配a/b/c其中一个字符
|用来多个模式或,模式1|模式2),满足任意一个就命中。;;必须写,代表分支结束;少写会继续往下执行下一个分支(穿透)。*)放最后,所有都不匹配时执行,相当于 default,可选。
例子:匹配数字
#!/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解析启动参数:
#!/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个字符 |
语法模板:
case "$var" in
模式) 命令 ;;
esac
逐个详解 + case 示例
1. * 任意字符(0或多个)
*.log:以.log结尾的字符串test*:以test开头*error*:包含 error*:匹配所有内容,一般放在最后做默认分支
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
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标准)
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]才是两个数字。
组合使用示例
str="a5"
case "$str" in
[a-z][0-9])
echo "1个小写字母 + 1个数字"
;;
esac
a5 ✔;aa ❌;a55 ❌
多模式匹配
模式1|模式2,满足任意一个就匹配
case "$opt" in
start|restart)
echo "启动或重启"
;;
*.jpg|*.png|*.gif)
echo "图片文件"
;;
esac
误区
❌ 误区1:case里面写正则
case 不支持正则!
- 不能用
^开头锚定、$结尾锚定、.代表任意字符、+多次匹配# 错误写法!case不识别 ^ case "$var" in ^test) echo 匹配 ;; esac想要正则匹配:改用
if [[ $var =~ 正则 ]]
❌ 误区2:* 匹配换行
case 是字符串比较,变量默认按单行处理,一般不匹配换行。
❌ 误区3:[0-9] 匹配多个数字
[0-9] 只匹配一个数字。
匹配1~多位数字:case原生glob做不到,要用:
if [[ $num =~ ^[0-9]+$ ]];then
echo 纯数字
fi
❌ 误区4:变量不加双引号 "$var"
如果变量值包含空格、特殊字符,不加引号会分词破坏匹配。case里变量建议永远双引号包裹。
glob 转义
如果想把 * ? [ 当成普通字符,需要转义:\*、\?、\[
s="a*b"
case "$s" in
a\*b)
echo "字符串是a*b"
;;
esac
case 和 if 的区别
case:字符串模式匹配,适合多值枚举、文件名、参数判断,代码清爽;只能做等值/通配匹配,不能直接比较大小(不能写$a -gt 10)if:适合逻辑运算、数值比较、复杂条件,&& ||组合更灵活
如果要在case里做数值大小判断,可以配合 (( )) 或命令返回值:
read n
case 1 in
$(( n > 10 )) )
echo "大于10"
;;
esac
常见坑
- 漏写
;;→ 分支穿透,多个分支一起执行 - 模式后少写右括号
)→ 语法报错 - 变量不加引号,变量带空格时解析异常
- 把正则写进case模式:case不是正则!是shell glob通配符,不能直接用
.*、^、$,这点很容易踩坑。如果要用正则匹配,改用
if [[ $var =~ 正则 ]]