简介
case
语句是一种多路分支结构,用于根据变量的值来判断执行不同的命令。作用与 if 有着异曲同工之妙,在某些地方比 if 可能更加好用,这里就介绍一些 case 的用法与实践,if 的详细方法见另一篇文章:shell if判断的应用方法-CSDN博客
文章目录如下
[1. case 的基本语法](#1. case 的基本语法)
[2. 正则表达式的用法](#2. 正则表达式的用法)
[2.1. 分隔符匹配](#2.1. 分隔符匹配)
[2.2. 通配符匹配](#2.2. 通配符匹配)
[2.3. 范围匹配](#2.3. 范围匹配)
[3. 实际应用场景](#3. 实际应用场景)
[3.1. 修改变量](#3.1. 修改变量)
[3.2. 匹配IP长度](#3.2. 匹配IP长度)
[3.3. 读取交互的变量](#3.3. 读取交互的变量)
[3.4. 检查文件后缀](#3.4. 检查文件后缀)
1. case 的基本语法
bash
case [var] in # var是需要判断的变量名,case in是固定的
str1) # 判读var变量是str1
command1 # 如果变量是"str1",则执行这里的命令
;; # 固定结尾语法
str2) # 判读var变量是str2
command2 # 如果变量是"str2",则执行这里的命令
;; # 固定结尾语法
*) # 如果变量既不是str1又不是str2,那么执行这里的命令
command3 # 自定义命令
;; # 固定结尾语法
esac # 固定case的结尾语法
case 语法的开头是 case 变量 in ,意思就是使用 case 语法读取某个变量,根据变量不同的结果执行不同的命令。
esac 是语法的结尾符,就是 case 倒过来写。
【例子】如果参数为1,调用函数Func1的方法;如果参数为2,调用函数Func2的方法;如果不是1或2,则调用函数Func3的方法。
bash
# 封装3个函数
Func1(){
echo "我是函数1"
}
Func2(){
echo "我是函数2"
}
Func3(){
echo "我是函数3"
}
# 使用case判断参数
case $1 in # 判断位置参数1的结果
1) # 如果为1,执行下面的代码
Func1
;;
2) # 如果为2,执行下面的代码
Func2
;;
*) # 如果非1或2,执行下面的代码
Func3
;;
esac # 结束语法
结果如下
- 参数为1,执行函数1。
- 参数为2,执行函数2。
- 参数非1或2,执行函数3。
不论是位置参数还是变量,我们都可以使用这种方法判断
bash
# 定义一个变量
var="A"
# 判断这个变量
case ${var} in
A)
echo "变量为A"
;;
*)
echo "变量不为A"
;;
esac
也可以直接使用命令来做判断
bash
# 判断命令的结果
case $(ls file.txt) in
file.txt)
echo "有file.txt这个文件"
;;
*)
echo "没有file.txt这个文件"
;;
esac
case 除了可以直接使用,也支持语句嵌套
bash
# 定义2个变量
a=$1
b=$2
# 判断变量a
case ${a} in
1)
# 如果a为1,判断b
case ${b} in
2)
echo "a=1, b=2"
;;
*)
echo "a=1, b!=2"
;;
esac
;;
*)
echo "a!=1"
;;
esac
- 如果a为1,判断b
- 如果b为2,执行xxx
- 如果b不为2,执行xxx
- 如果a不为1,执行xxx
2. 正则表达式的用法
正则表达式能够将 case 的用法完全发挥,这里列举3种常用的方法。
2.1. 分隔符匹配
bash
yes|YES|Yes) # 使用 | 分割
基本语法在《目录1》已经介绍过,平时使用最多就是判断某个变量是否=xxx。这些变量可以自定义,也可以通过某些命令获取的值。当出现多个值时,那么使用固定的值判断就显得有些局限。需求如下:
- 判断变量 var 是 yes 或 YES 或 Yes,执行 Func1
- 判断变量 var 是 no 或 NO 或 No,执行 Func2
- 如果既不是 yes,也不是 no,执行 Func3
bash
# 定义一个变量
var="$1"
# 封装3个函数
Func1(){
echo "我是yes指定的函数1"
}
Func2(){
echo "我是no指定的函数2"
}
Func3(){
echo "我是非yes或no指定的函数3"
}
# 使用case判断参数
case ${var} in
yes|YES|Yes)
Func1
;;
no|NO|No)
Func2
;;
*)
Func3
;;
esac
结果如下
2.2. 通配符匹配
bash
字符*) 或者 *字符) # *匹配0个或多个字符
字符?) 或者 ?字符) # ?匹配1个字符
当获取的变量存在多个字符,但只能确定字符中包括xxx字符时,那么通配符的作用就展示出来了。需求如下:
- 判断路径是否包含 file 路径
bash
path=$(pwd)
case ${path} in
*/file*)
echo "当前路径包含 file 目录"
;;
*)
echo "当前路径不包含 file 目录"
;;
esac
*/file* 表示 /file 左右可以出现任意字符。
*/file 表示 /file 左边可以出现任意字符。
/file* 表示 /file 右边可以出现任意字符。
除了常用的 * 符号,还有一个不常用的 ? 符号,来看一个例子
bash
case $1 in
"a"?)
echo "位置参数为a+1个任意字符"
;;
?"a")
echo "位置参数为任意1个字符+a"
;;
*)
echo "位置参数为a或者其他"
;;
esac
使用 ? 符号挨着需要匹配的字符串旁边。以匹配字符 a 为例,表示匹配变量为2个字符。
- a?:表示a后面接任意一个字符
- ?a:表示a前面接任意一个字符
2.3. 范围匹配
- 这里主要介绍 [ ] 符号:匹配一个范围字符,但 case 中貌似不支持 [字符]{次数}
【案例一】匹配一个大写字母 [A-Z]
bash
case "$1" in
[A-Z])
echo "这是1个大写字母"
;;
esac
【案例二】匹配一个小写字母 [a-z]
bash
case "$1" in
[a-z])
echo "这是1个小写字母"
;;
esac
【案例三】匹配一个数字 [0-9]
bash
case "$1" in
[0-9])
echo "这是1个数字"
;;
esac
【案例四】匹配一个数字或字母(不包括特殊字符)[0-9] | [a-z] | [A-Z]
bash
case "$1" in
[0-9]|[a-z]|[A-Z])
echo "这是1个数字或字母"
;;
esac
也可以这样写 [0-9a-zA-Z]
bash
case "$1" in
[0-9a-zA-Z])
echo "这是1个数字或字母"
;;
esac
【案例五】匹配多个字母或多个数字 [0-9][0-9][0-9]
bash
case "$1" in
[0-9][0-9][0-9])
echo "这是3个数字"
;;
[a-z][a-z][a-z])
echo "这是3个小写字母"
;;
[A-Z][A-Z][A-Z])
echo "这是3个大写字母"
;;
esac
case 中匹配多个字符只有使用多个**[ ][ ][ ]** 的方法,[a-z]{次数} 这种方式在case中不支持。
【案例六】匹配以a开头的字符 a*
bash
case "$1" in
a*)
echo "这是1个以a开头的字符"
;;
esac
【案例七】匹配以a结尾的字符 *a
bash
case "$1" in
*a)
echo "这是1个以a结尾的字符"
;;
esac
3. 实际应用场景
3.1. 修改变量
需求如下:
- 如果网卡名为 ens33,那么执行A方法
- 如果网卡名为 ens192,那么执行B方法
- 如果网卡名不是 ens33 或 ens192,那么修改原变量,执行C方法
bash
# 读取某个值赋值给变量
var=$(ip route get 8.8.8.8 |awk -F ' src' 'NR==1{print $1}' |awk '{print $NF}')
case ${var} in
"ens33")
echo "执行A方法"
;;
"ens192")
echo "执行B方法"
;;
*)
var="ens100"
echo "var的值超过范围,重新定义后执行C方法"
;;
esac
3.2. 匹配IP长度
方法参考《2.3. 正则表达式匹配》,需求如下:
- IP以192开头
- IP中间每段数字都是3个
bash
case "$1" in
192.[0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9])
echo "这是1个以192开头,全3位的IP"
;;
*)
echo "IP不正确"
;;
esac
3.3. 读取交互的变量
需求如下:
- 用户传入 yes 或 YES 或 y 或 Y 表示删除某个文件
- 用户传入 no 或 NO 或 n 或 N 表示不删除某个文件
- 用户传入其他参数需给出提示:重新传入
bash
while read -p "是否删除文件file1.txt: " r;do
case ${r} in
yes|YES|y|Y)
echo "删除文件file1.txt后退出"
rm -rf file1.txt
break
;;
no|NO|n|N)
echo "不删除文件file1.txt,直接退出"
break
;;
esac
done
结果如下
3.4. 检查文件后缀
需求如下:
- 文件如果是文本文件,执行xxx
- 文件如果是图片文件,执行xxx
- 文件即不是文本文件,又不是图片文件,执行xxx
bash
case "$1" in
*.txt)
echo "这是一个文本文件,执行xxx"
;;
*.jpg | *.png)
echo "这是一个图片文件,执行xxx"
;;
*)
echo "该文件不符合需求,执行xxx"
;;
esac