getopt 具有可选值的可选参数

getopt 具有可选值的可选参数

我正在使用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 getoptOUTPUT部分下方,您会看到它说:

如果选项采用可选参数,但未找到任何参数,则将生成下一个参数,但在引用模式下为空,但在不带引号(兼容)模式下不会生成第二个参数。

这意味着(如果您没有在兼容模式下运行它,并且对于非旧版脚本没有什么理由这样做)getopt将为该选项生成一个参数,可以是空的,也可以是带有可选值的,并将其添加到紧接在选项之后的参数列表。

这意味着选项后面总是有一个参数,所以你总是需要shift 2.

顺便说一句,对于可选参数,您可能应该nl在 while/case 循环之前设置为其默认值,或者使用带有默认值的参数扩展。例如

nl="${2:-default_value}"

您可能还应该在同一个 case 语句中测试短选项和长选项,否则您将不必要地重复代码来处理长和短变体。例如:

-l|--long) ... ;;

相关内容