只有当所有选项都预先提供时,“getopts”才有用吗?

只有当所有选项都预先提供时,“getopts”才有用吗?

我正在尝试查看是否可以用于getopts我的 Bash 脚本。但是,我不确定出了什么问题:

#! /bin/bash

while getopts "a:b" opt ; do
    case $opt in
        a)
            A_OPTION="option a was given argument $OPTARG"
            ;;
        b)
            B_OPTION="option b was found"
            ;;
    esac
done
if [ -n "$A_OPTION" ] ; then echo $A_OPTION ; fi
if [ -n "$B_OPTION" ] ; then echo $B_OPTION ; fi
shift $((OPTIND - 1))
echo "The remaining arguments are: $@"

输出是:

$ ./getopts-test foo goo -a moo -b
The remaining arguments are: foo goo -a moo -b
$ ./getopts-test -a moo -b foo goo
option a was given argument moo
option b was found
The remaining arguments are: foo goo
$ ./getopts-test -a moo foo goo -b
option a was given argument moo
The remaining arguments are: foo goo -b
$ ./getopts-test -b foo goo -a moo
option b was found
The remaining arguments are: foo goo -a moo

为什么脚本没有在所有情况下检测到选项?getopts仅当选项全部预先提供并且不与其他参数混合时才有用吗?

答案1

(这太长了,无法成为评论,也太差了,无法成为答案)

getopt尝试检测带-(减号)的单字母选项和带参数的选项。

当没有(不再)选项(no -b,no -a foo)时它就会停止。它不会解析完整列表。

所以第二个问题的答案是肯定的。

您可能希望自己编写一个 getopt 解析器并处理-foo --bar争论(例如文件、字符串)或选项的问题。

长期以来的传统是将选项放在前面,参数放在后面,这样您就知道选项何时停止,以及是否-foo是实际的文件名。

答案2

根据联机帮助页,这是预期的行为。getopts支持“选项”和“选项参数”。

准则 4:所有选项均应以 开头-。话虽这么说,但./getopts-test foo goo -a moo -b不会起作用,因为“foo”既不是选项,也不是选项参数。因此,它将停止。

选项参数由“:”指定。在您的定义中,a:是一个选项参数,它解析-a moo并且b只是-b在 中解析的选项./getopts-test -a moo -b foo goo。剩下的(foo goo)就剩下了。

准则 8:选项参数的所有参数均应以一个逗号分隔。这就是为什么./getopts-test -a moo foo goo -b只解析-a moo.正确的做法是./getopts-test -a moo,foo,goo -b。 (同样适用于你的最后一个案例)

参考:

相关内容