shell case判断的实际应用

发布时间:2024年01月02日

简介

? 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变量是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的方法。

# 封装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} in
    A)
        echo "变量为A"
        ;;
    *)
        echo "变量不为A"
        ;;
esac

????????

也可以直接使用命令来做判断

# 判断命令的结果
case $(ls file.txt) in
    file.txt)
        echo "有file.txt这个文件"
        ;;
    *)
        echo "没有file.txt这个文件"
        ;;
esac

????????

case 除了可以直接使用,也支持语句嵌套

# 定义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. 分隔符匹配

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} in
    yes|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" in
    a*)
        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" 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?表示不删除某个文件
  • 用户传入其他参数需给出提示:重新传入
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
case "$1" in
    *.txt)
        echo "这是一个文本文件,执行xxx"
        ;;
    *.jpg | *.png)
        echo "这是一个图片文件,执行xxx"
        ;;
    *)
        echo "该文件不符合需求,执行xxx"
        ;;
esac

????????

文章来源:https://blog.csdn.net/m0_61066945/article/details/135269454
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。