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