在 Linux 的 Bash shell 中, case 复合命令(compound command)可以在匹配特定的模式时,执行相应的命令。查看 man bash 里面对 case 命令的说明如下:

case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
A case command first expands word, and tries to match it against each pattern in turn The word is expanded using tilde expansion, parameter and variable expansion, arithmetic substitution, command substitution, process substitution and quote removal.

Each pattern examined is expanded using tilde expansion, parameter and variable expansion, arithmetic substitution, command substitution, and process substitution. When a match is found, the corresponding list is executed.

If the ;; operator is used, no subsequent matches are attempted after the first pattern match. Using ;& in place of ;; causes execution to continue with the list associated with the next set of patterns. Using ;;& in place of ;; causes the shell to test the next pattern list in the statement, if any, and execute any associated list on a successful match.

The exit status is zero if no pattern matches. Otherwise, it is the exit status of the last command executed in list.

注意case 这个关键字是 bash 的内置命令,该命令要求最后一个参数必须是 esacesac 关键字自身并不是 bash 的内置命令,它仅仅只是 case 命令要求必须提供的一个参数而已。

下面以一个 testcase.sh 脚本来举例说明 case 命令的详细用法,脚本内容如下:

#!/bin/bash

var=4
case $1 in
    1) echo "Your input is 1." ;;
    2 | 3 | 4)
        echo "Your input is 2, or 3, or 4."
        ;;&
    $var)
        echo "Sure, your input is 4."
        ;;
    lion)
        echo "Your input is lion."
        ;;
    "big lion")
        echo "Your input is big lion."
        ;&
    "fall through from big lion")
        echo "This is fall through from big lion."
        ;;
    *)
        echo "Your input is not supported."
        ;;
esac

执行这个脚本的结果如下:

$ ./testcase.sh 1
Your input is 1.
$ ./testcase.sh 2
Your input is 2, or 3, or 4.
Your input is not supported.
$ ./testcase.sh 4
Your input is 2, or 3, or 4.
Sure, your input is 4.
$ ./testcase.sh lion
Your input is lion.
$ ./testcase.sh "big lion"
Your input is big lion.
This is fall through from big lion.
$ ./testcase.sh tiger
Your input is not supported.

对这个执行结果和脚本的关键点说明如下:

  • case 命令后面跟着的参数是被匹配的模式,这里用 $1 来获取执行脚本时传入的第一个参数。在 in 参数跟着可以处理的模式列表,每一项用 ) 作为结尾。
  • 可以用 2 | 3 | 4) 这样的形式来匹配多个模式,每个模式用 | 隔开。如果写为 1) | 2) | 3) 的形式会报错。即,只有最后一个模式才用 ) 来结尾。
  • 模式列表不限于数字,可以是不带引号的字符串、带引号的字符串、bash 的扩展语句、通配符,等等。例如上面使用了 $var 来匹配 var 变量的值。
  • 如果要匹配的字符串带有空格,一定要用引号括起来,否则会报错。
  • 可以使用 * 通配符来表示匹配任意内容,类似于默认分支语句,这个语句一定要写在最后面,否则会先匹配到它,影响它后面语句的匹配。
  • 每个模式处理完之后,一定要用 ;;;&、或者 ;;& 来结尾。如果这三个都没有提供则会报错。
  • ;; 表示不再往下匹配,会结束整个 case 命令的执行。作用类似于在 select 中执行 break 命令。
  • ;& 表示继续执行下面一个模式里面的语句,不检查下一个模式是否匹配。上面的 "big lion") 模式使用了 ;& 结尾,从执行结果可以看到,它会往下执行 "fall through from big lion") 模式的语句。
  • ;;& 表示继续往下匹配,如果找到匹配的模式,则执行该模式里面的语句。上面的 2 | 3 | 4) 模式使用了 ;;& 结尾,当匹配到 2 时,它继续往下匹配,中间没有找到匹配项,一直到 *) 才匹配,执行了 *) 模式里面的语句。当匹配到 4 时,往下匹配到了 $var) 模式,然后 $var) 模式里面用 ;; 结束执行,没有再往下匹配。

在实际应用中,可以把 case 命令和 getopts 命令结合使用,getopts 命令获取执行脚本时传入的选项参数,case 命令根据不同的选项参数进行不同的处理。一个简单的示例如下:

while getopts "bf" arg; do
    case ${arg} in
        b) handle_option_b ;;
        f) handle_option_f ;;
        ?) show_help ;;
    esac
done

也可以把 select 命令 和 case 命令结合使用,select 命令获取用户选择的项,case 命令根据用户选择的不同项进行不同的处理。这里不再举例。


霜鱼片
446 声望331 粉丝

解读权威文档,编写易懂文章。如有恰好解答您的疑问,多谢赞赏支持~