为什么我不能使用getopt在选项和可选参数之间有空格?

pdi*_*izz 6 bash getopt

使用getopt来解析命令行参数时,可以在选项标志和必需参数的参数之间放置一个空格,但不在可选参数之间.只有在选项之后,才会解析可选参数.

TEMP=`getopt -o p:q:: -n 'mkqueue.sh' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

# Now go through all the options
while true ; do
    case "$1" in
        -p) echo "Option p, argument \`$2'" ; shift 2 ;;
        -q) 
            case "$2" in
                "") echo "Option q, no argument"; shift 2 ;;
                *)  echo "Option q, argument \`$2'" ; shift 2 ;;
            esac ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done
Run Code Online (Sandbox Code Playgroud)

(基于此:http://software.frodo.looijaard.name/getopt/docs/getopt-parse.bash)

当我运行没有可选参数的脚本时,它可以工作:

./mkqueue.sh -p adfsa -q
Option p, argument `adfsa'
Option q, no argument
Run Code Online (Sandbox Code Playgroud)

如果我尝试将可选参数添加到-q并在其间有空格,则它不起作用:

./mkqueue.sh -p adfsa -q sdfasdfa
Option p, argument `adfsa'
Option q, no argument
Run Code Online (Sandbox Code Playgroud)

如果您在选项和参数之间没有空格,即使必需参数与空间一起使用,它也可以工作:

./mkqueue.sh -p adfsa -qsdfasdfa
Option p, argument `adfsa'
Option q, argument `sdfasdfa'
Run Code Online (Sandbox Code Playgroud)

有没有解决这个问题?

ric*_*ici 9

该限制在联机帮助页中记录getopt:

一个简单的短选项是" - "后跟一个短选项字符.如果该选项具有必需参数,则可以直接在选项字符之后或作为下一个参数(即由命令行上的空格分隔)写入.如果该选项具有可选参数,则必须在选项字符(如果存在)之后直接写入.

虽然getopt允许"可选选项参数",但它们通常被认为是一个坏主意.例如,Posix 实用程序语法指南包括:

准则7:选项参数不应是可选的.

本指南的基本原因是按照惯例,命令行选项的参数可以是任何字符串.例如,它可能看起来像另一种选择.它可能是文字字符串--,通常表示选项列表的结尾.它可能是一个空字符串.任何东西.

"可选选项参数"的问题在于,知道未提供可选选项参数的唯一方法是将以下参数识别为选项或--.但这意味着可选参数的值不能以a开头-.

或者,您可以选择getopt命令行实用程序采用的解决方案,即要求可选参数紧跟在该选项之后,而没有中间空格(即,在同一个单词中).但在这种情况下,可选参数不能是空字符串.

而不是创建复杂的规则来解决这些歧义,Posix推荐的简单解决方案(并且,我的权限很少) - 是不允许选项参数是可选的.如果命令行选项有一个共同的值,并且您希望通过不要求键入它来简化用户的生命周期,那么实现两个不同的命令行选项,其中一个选择参数,另一个选择参数没有.常见技术包括对不带参数的版本使用小写字符,对带有参数的版本使用相应的大写字符,或者对该版本使用long选项(--option).

对于那些喜欢密集和有说服力的解释的人,Posix的理由解释说:

准则7允许任何字符串作为选项参数; option-argument可以以任何字符开头,可以是-or --,也可以是空字符串.例如,命令pr -h -,pr -h --,pr -h -d,pr -h +2,和pr -h ''包含选项参数-,--,-d,+2,和一个空字符串,分别.相反,该命令pr -h -- -d将-d视为一个选项,而不是参数,因为这里--是一个选项参数,而不是分隔符.