如何生成Bash中getopts不可接受的参数列表?

时间:2013-12-26 23:22:16

标签: bash arguments options getopts

假设我在Bash脚本中使用选项字符串“:a:b”运行getopts,并提供以下命令行参数:

./script.sh -a foo bar -b bar zappo

“foo”的实例是选项a的预期参数,而选项b没有预期的参数。但是,“bar”的实例和“zappo”的实例都是getopts不可接受的。运行getopts后,如何回显包含所有不可接受参数列表的变量?我怎么能生成“bar bar zappo”列表?谢谢!

以下是为方便起见的一些代码:

#!/bin.bash
option_string=":a:b"
unexpected_parameters=""
OPTIND=1
while getopts "${option_string}" options; do
    case ${options} in
        a)
            echo "-a triggered with parameter ${OPTARG}" >&2 # output to STDERR
            ;;
        b)
            echo "-b triggered" >&2 # output to STDERR
            ;;
        \?)
            echo "invalid option: -${OPTARG}" >&2 # output to STDERR
            ;;
    esac
    #<insert code magic... unexpected_parameters="${unexpected_parameters} "$(MAGIC)"">
done
echo "unexpected parameters: ${unexpected_parameters}"

1 个答案:

答案 0 :(得分:1)

getopts停止在第一个非选项参数处理。这是Posix风格的参数处理。在Posix风格的参数处理中,给出命令

utility -a foo bar -b bar zappo

utility不会将-b解释为命令行标志。如果-a接受一个参数,那么bar将是第一个位置参数,然后会有三个位置参数,-bbar和{{1} }。

GNU通过置换命令行参数来扩展此语法,以便标志选项可以位于命令行中的任何位置。但是,如果设置环境变量zappo,那么GNU实用程序(大多数)将像普通的Posix实用程序一样运行。 Posix C库函数POSIXLY_CORRECT(和getopt(3))的GNU版本默认使用GNU语法,并且还适用于getopt_long(3)环境变量。

然而,bash POSIXLY_CORRECT内置版本是严格的Posix风格。因此,在您的情况下,对于getopts,对于带有参数getopts ":a:b"的标记a,您的循环将只执行一次。当foo终止时,getopts将设置第一个未使用的命令行参数的索引,在本例中为OPTIND3)。

如果你想使用bar进行GNU风格的选项处理,你必须自己进行置换。例如,你可以这样做:

getopts

或者,您可以使用# Positional arguments are not necessarily unexpected; in fact, they are usually # expected. So I accumulate them here in a bash array positional=() while (($#)); do # If you really wanted to do GNU style processing, you'd need to special case # '--' and "long options" starting with '--'. Here, I just do the simplest # thing, which is to pass anything that vaguely looks like an optional argument # (starts with a -) to getopts. if [[ $1 = -* ]]; then # Grab some options: while getopts "$option_string" option; do case $option in a) ... ;; # etc. esac done # get rid of whichever options we've handled and reset OPTIND shift $((OPTIND - 1)) OPTIND = 1 else # Accumulate and ditch the positional argument: positional+=("$1") shift fi done 的GNU实现,它将为您完成所有这些,但代价是更烦人的界面。 (至少,我发现它很烦人,但YMMV。)