shell case判断的实际应用

简介

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
相关推荐
Cachel wood12 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Youkiup20 分钟前
【linux 常用命令】
linux·运维·服务器
qq_4336184420 分钟前
shell 编程(二)
开发语言·bash·shell
qq_2975046124 分钟前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
weixin_4373982137 分钟前
Linux扩展——shell编程
linux·运维·服务器·bash
小燚~39 分钟前
ubuntu开机进入initramfs状态
linux·运维·ubuntu
小林熬夜学编程1 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
炫彩@之星1 小时前
Windows和Linux安全配置和加固
linux·windows·安全·系统安全配置和加固
hhhhhhh_hhhhhh_1 小时前
ubuntu18.04连接不上网络问题
linux·运维·ubuntu
冷心笑看丽美人1 小时前
探秘 DNS 服务器:揭开域名解析的神秘面纱
linux·运维·服务器·dns