bash getopts在while循环vs命令行中的行为不同

时间:2018-04-12 23:50:11

标签: bash shell

命令行

$ getopts ":mnopq:rs" Option -q
$ echo $Option 
?
$ echo $OPTARG

鉴于

$ cat getopt.sh 
#!/bin/bash

echo '$@' is $@
while getopts ":mnopq:rs" Option
do
  echo Option is  $Option  
  echo OPTARG is $OPTARG  
  case $Option in
    m     ) echo "Scenario #1: option -m-   [OPTIND=${OPTIND}]";;
    n | o ) echo "Scenario #2: option -$Option-   [OPTIND=${OPTIND}]";;
    p     ) echo "Scenario #3: option -p-   [OPTIND=${OPTIND}]";;
    q     ) echo "Scenario #4: option -q-\
                  with argument \"$OPTARG\"   [OPTIND=${OPTIND}]";;
    #  Note that option 'q' must have an associated argument,
    #+ otherwise it falls through to the default.
    r | s ) echo "Scenario #5: option -$Option-";;
    *     ) echo "Unimplemented option chosen.";;   # Default.
  esac
done

我得到了

脚本

$ ./getopt.sh -q
$@ is -q
Option is :
OPTARG is q
Unimplemented option chosen.

为什么Commandline和Script之间的输出存在差异?

1 个答案:

答案 0 :(得分:4)

您是否在同一个shell中多次运行“Commandline”测试? getopts使用变量OPTIND来跟踪它在参数列表中的位置,因此它不会一遍又一遍地处理相同的选项。因此,如果您多次运行测试,它将跳过上次处理的内容。在你的情况下,我怀疑这是让它认为它在参数列表的末尾(在这种情况下,它的退出状态为1)。以下是bash手册页的摘录:

  

[...]每次调用它时,getopts都会放置[...]索引   要处理到变量OPTIND的下一个参数。 OPTIND   每次调用shell或shell脚本时,都会初始化为1。   [...] shell不会自动重置OPTIND;它   必须在多次调用getopts之间手动重置   如果要使用一组新参数,则调用相同的shell。

以下是一个例子:

$ getopts ":mnopq:rs" Option -q
$ echo "status=$?, Option='$Option', OPTARG='$OPTARG', OPTIND=$OPTIND"
status=0, Option=':', OPTARG='q', OPTIND=2
$
$ getopts ":mnopq:rs" Option -q
$ echo "status=$?, Option='$Option', OPTARG='$OPTARG', OPTIND=$OPTIND"
status=1, Option='?', OPTARG='', OPTIND=2
$
$ unset OPTIND
$ getopts ":mnopq:rs" Option -q
$ echo "status=$?, Option='$Option', OPTARG='$OPTARG', OPTIND=$OPTIND"
status=0, Option=':', OPTARG='q', OPTIND=2

它第一次达到您的期望。第二次它表明它没有处理选项,这与您所看到的相匹配。第三次OPTIND未设置,因此默认返回参数列表的开头。