Linux程序设计:case分支

       使用一系列的 if 命令来识别哪一个可能的选项已经被选中。这种类型的构造经常出现在程序中,出现频率如此之多,以至于许多编程语言(包括shell)专门为多选决策提供了一种流程控制机制。

case

Bash 的多选复合命令称为case。它的语法规则如下所示:

case word in
       [pattern [| pattern]...) commands ;;]...
esac

之前的读菜单程序,用来应对一个用户选项的逻辑流程:

#!/bin/bash
# read-menu: a menu driven system information program
clear
echo "
      Please Select:
        1. Display System Information
        2. Display Disk Space
        3. Display Home Space Utilization
        0. Quit
"
read -p "Enter selection [0-3] > "

if [[ $REPLY =~ ^[0-3]$ ]]; then
        if [[ $REPLY == 0 ]]; then
            echo "Program terminated."  
            exit
        fi
        if [[ $REPLY == 1 ]]; then
            echo "Hostname: $HOSTNAME"
            uptime
            exit
        fi
        if [[ $REPLY == 2 ]]; then
            df -h
            exit
        fi
        if [[ $REPLY == 3 ]]; then
            if [[ $(id -u) -eq 0 ]]; then 
                echo "Home Space Utilization (All Users)"
                du -sh /home/*
            else
                echo "Home Space Utilization ($USER)"
                du -sh $HOME
            fi
            exit
        fi
else
        echo "Invalid entry." >&2
exit 1
fi

使用case 语句,我们可以用更简单的代码替换这种逻辑:

#!/bin/bash
# case-menu: a menu driven system information program
clear
echo "
     Please Select:
         1. Display System Information
         2. Display Disk Space
         3. Display Home Space Utilization
         0. Quit
"
read -p "Enter selection [0-3] > "
case $REPLY in
      0) echo "Program terminated."
      exit
      ;;
      1) echo "Hostname: $HOSTNAME"
       uptime
       ;;
       2) df -h
       ;;
       3) if [[ $(id -u) -eq 0 ]]; then
                echo "Home Space Utilization (All Users)"
                du -sh /home/*
          else
                echo "Home Space Utilization ($USER)"
                du -sh $HOME
           fi
           ;;
       *) echo "Invalid entry" >&2
          exit 1
         ;;
esac

       case 命令检查一个变量值,在我们这个例子中,就是REPLY 变量的变量值,然后试图去匹配其中一个具体的模式。当与之相匹配的模式找到之后,就会执行与该模式相关联的命令。若找到一个模式之后,就不会再继续寻找。

模式

这里case 语句使用的模式和路径展开中使用的那些是一样的。模式以一个“)”为终止符。这里是一些有效的模式。

模式                  描述
a)                     若单词为“a”,则匹配
[[:alpha:]])        若单词是一个字母字符,则匹配
???)                 若单词只有3 个字符,则匹配
*.txt)                若单词以“.txt”字符结尾,则匹配
*)                     匹配任意单词。把这个模式做为case 命令的最后一个模式,
是一个很好的做法,可以捕捉到任意一个与先前模式不匹配的数值;也就是说,捕捉到任何可能的无效值。

这里是一个模式使用实例:

#!/bin/bash
read -p "enter word > "
case $REPLY in
          [[:alpha:]]) echo "is a single alphabetic character." ;;
          [ABC][0-9]) echo "is A, B, or C followed by a digit." ;;
          ???) echo "is three characters long." ;;
          *.txt) echo "is a word ending in '.txt'" ;;
          *) echo "is something else." ;;
esac

还可以使用竖线字符作为分隔符,把多个模式结合起来。这就创建了一个“或”条件模式。这对于处理诸如大小写字符很有用处。例如:

#!/bin/bash
# case-menu: a menu driven system information program
clear
echo "
   Please Select:
           A. Display System Information
           B. Display Disk Space
           C. Display Home Space Utilization
           Q. Quit
"
read -p "Enter selection [A, B, C or Q] > "
case $REPLY in
           q|Q) echo "Program terminated."
           exit
            ;;
           a|A) echo "Hostname: $HOSTNAME"
           uptime
            ;;
           b|B) df -h
            ;;
           c|C) if [[ $(id -u) -eq 0 ]]; then
                        echo "Home Space Utilization (All Users)"
                        du -sh /home/*
                  else
                         echo "Home Space Utilization ($USER)"
                         du -sh $HOME
                         fi
                         ;;
            *) echo "Invalid entry" >&2
              exit 1
              ;;
esac

       这里,我们更改了case-menu 程序的代码,用字母来代替数字做为菜单选项。注意新模式如何使得大小写字母都是有效的输入选项。

执行多个动作

       早于版本号4.0 的bash,case 语法只允许执行与一个成功匹配的模式相关联的动作。匹配成功之后,命令将会终止。这里我们看一个测试一个字符的脚本:

#!/bin/bash
# case4-1: test a character
read -n 1 -p "Type a character > "
echo
case $REPLY in
        [[:upper:]]) echo "'$REPLY' is upper case." ;;
        [[:lower:]]) echo "'$REPLY' is lower case." ;;
        [[:alpha:]]) echo "'$REPLY' is alphabetic." ;;
        [[:digit:]]) echo "'$REPLY' is a digit." ;;
        [[:graph:]]) echo "'$REPLY' is a visible character." ;;
        [[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;
        [[:space:]]) echo "'$REPLY' is a whitespace character." ;;
        [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;
esac

运行这个脚本,输出这些内容:

[me@linuxbox ~]$ case4-1
Type a character > a
'a' is lower case.

       大多数情况下这个脚本工作是正常的,但若输入的字符不止与一个POSIX 字符集匹配的话,这时脚本就会出错。例如,字符“a”既是小写字母,也是一个十六进制的数字。早于4.0的bash,对于case 语法绝不能匹配多个测试条件。现在的bash 版本,添加“;;&”表达式来终止每个行动,所以现在我们可以做到这一点:

#!/bin/bash
# case4-2: test a character
read -n 1 -p "Type a character > "
echo
case $REPLY in
         [[:upper:]]) echo "'$REPLY' is upper case." ;;&
         [[:lower:]]) echo "'$REPLY' is lower case." ;;&
         [[:alpha:]]) echo "'$REPLY' is alphabetic." ;;&
         [[:digit:]]) echo "'$REPLY' is a digit." ;;&
         [[:graph:]]) echo "'$REPLY' is a visible character." ;;&
         [[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;&
         [[:space:]]) echo "'$REPLY' is a whitespace character." ;;&
         [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;&
esac

当我们运行这个脚本的时候,我们得到这些:

[me@linuxbox ~]$ case4-2
Type a character > a
'a' is lower case.
'a' is alphabetic.
'a' is a visible character.
'a' is a hexadecimal digit.

添加的“;;&”的语法允许case 语句继续执行下一条测试,而不是简单地终止运行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值