Bash case语句:检索有效选项列表?

时间:2014-07-10 11:55:01

标签: bash

有没有办法检索案例陈述中的选项列表?例如,如果我有这个代码:

tool=$1

case ${tool} in 
     brdf)
        # Do stuff
        ;;
     drift)
        # Do other stuff
        ;;
     *)
        echo "ERROR: I don't know this tool. Valid options are: brdf, drift"
        exit 1
        ;;
esac

这很容易理解,但是当从列表中添加/删除工具时,错误消息可能很容易过时,因为我需要记住在那里更改名称。

使用类似这样的数组可以避免重复:

tool=$1

validtools=(brdf drift)

case ${tool} in
     ${validtools[0]})
           # Do stuff
           ;;
     ${validtools[1]})
           # Do other stuff
           ;;
     *)
           echo "ERROR: I don't know this tool. Valid options are: ${validtools[@]}"
           exit 1
           ;;
esac

但是阅读起来非常糟糕,无论如何使用硬编码数组索引会更糟糕。

是否有一种很好的方法可以执行此操作,可能是某些变量或命令检索可用选项的列表,或者我只需记得在添加新选项时更新错误消息?

1 个答案:

答案 0 :(得分:3)

最常用的方式是第一个例子。查看linux中的所有init脚本。

这是有原因的,因为你可以使用如下构造:

case "$a" in
    arg1|arg2|arg3) ... ;;
    brg1|brg2) ... ;; 
    brg2) ... ;;
esac

并且会自动使用所有可能的变体自动使用usage message

这里也是shopt -s extglob,允许你在statemens中使用扩展模式匹配。有关示例,请参阅此答案:https://stackoverflow.com/a/4555979/632407

但是如果你想使用数组,尝试使用关联数组,增加一些可读性。 (但无论如何它都很糟糕):)喜欢下一个:

declare -A arg

initargs() { for a in "$@"; do arg[$a]="$a"; done; }

initargs brd lbrs ubrs

for myarg 
do
    case "$myarg" in
        ${arg[brd]}) echo "brd";;
        ${arg[ubrs]}) echo "ubrs";;
        ${arg[lbrs]}) echo "lbrs";;
        *) echo "Unknown arg =$myarg=. Known are: ${arg[@]}" ;;
    esac
done

所以允许的args是:“brd”“lbrs”“ubrs”和下一个输入的脚本

$ bash argtest ubrs badarg brd

产生

ubrs
Unknown arg =badarg=. Known are: lbrs ubrs brd
brd