我正在使用getopt
并希望有一个-l
带有可选值的选项。我发现,当在-l
没有提供参数值的情况下单独匹配时,我仍然必须使用shift 2
而不是仅使用一个shift
.这是怎么回事?这是怎么发生的?
opts=$( getopt -o "$shortopts" -l "$longopts" -n "${0##*/}" -- "$@" )
eval "set -- ${opts}"
while (( $# > 0 )); do
case $1 in
("-l")
case "$2" in
(+([[:digit:]]))
# matches -lNUM, optional argument value
nl="$2"; shift 2 ;;
(*)
# matches -l, no argument value provided
nl=1 ; shift ;;
esac
;;
("--") shift ; break ;;
(*) opt_error=1 ; break ;;
esac
done
答案1
如果您查看man getopt
该OUTPUT
部分下方,您会看到它说:
如果选项采用可选参数,但未找到任何参数,则将生成下一个参数,但在引用模式下为空,但在不带引号(兼容)模式下不会生成第二个参数。
这意味着(如果您没有在兼容模式下运行它,并且对于非旧版脚本没有什么理由这样做)getopt
将为该选项生成一个参数,可以是空的,也可以是带有可选值的,并将其添加到紧接在选项之后的参数列表。
这意味着选项后面总是有一个参数,所以你总是需要shift 2
.
顺便说一句,对于可选参数,您可能应该nl
在 while/case 循环之前设置为其默认值,或者使用带有默认值的参数扩展。例如
nl="${2:-default_value}"
您可能还应该在同一个 case 语句中测试短选项和长选项,否则您将不必要地重复代码来处理长和短变体。例如:
-l|--long) ... ;;