【问题标题】:Using getopts to read one optional parameter and shift the right number of arguments使用 getopts 读取一个可选参数并移动正确数量的参数
【发布时间】:2013-01-17 08:22:11
【问题描述】:

我正在编写一个简单的 bash 脚本,它采用一个可选参数 (-t),后跟一些附加参数。

我认为 getopts 是实现这一目标的合理方法,但我很难获得所需的行为。我有以下内容:

foo() {
    baz=10
    while getopts ":t:" option; do
        case "$option" in
        t) baz=$OPTARG ;;
        esac
    done
    shift $((OPTIND - 1))
    bar -t $baz $1 $2 $3
}

问题是$OPTIND 似乎并没有根据参数是否存在而有所不同,所以我没有像预期的那样使用可选参数获得正确的行为(即,我无法通过 shift 来切换正确数量的参数,无论参数是否存在)。

我希望以下两项都能正确执行:

foo a b c
foo -t 5 a b c

实现这一目标的最简单方法是什么?我更喜欢不是 hack 的解决方案,因为我可能想要使用额外的可选参数。

【问题讨论】:

    标签: bash


    【解决方案1】:

    看来您正在尝试编写 bash 函数,而不是 bash 脚本。 OPTIND 在调用 shell/脚本时设置为 1,但在调用函数时不设置为 1,因此具有不同参数的后续函数调用将继续在同一点解析。

    如果你想保留它作为一个函数,你可以手动重置它:

    foo() {
        OPTIND=1
        baz=10
        while getopts ":t:" option; do
            case "$option" in
            t) baz=$OPTARG ;;
            esac
        done
        echo $OPTIND
        shift $((OPTIND - 1))
        echo bar -t $baz $1 $2 $3
    }
    

    【讨论】:

      【解决方案2】:

      问题在于您永远不会重置$OPTIND,因此每次调用foo 时,它都会从最后处理的选项索引之后开始检查其参数。例如:

      # $OPTIND is now 1
      foo -t opt arg1 arg2 arg3
      # the above recognizes -t opt as an option, and sets $OPTIND to 3
      
      # $OPTIND is now 3
      foo arg4 arg5 arg6
      # the above recognizes that arg6 is not an option, so it leaves $OPTIND at 3
      

      解决方案是将$OPTIND 本地化到foo 内,显式设置为1

      foo() {
          baz=10
          local OPTIND=1
          while getopts ":t:" option; do
              case "$option" in
              t) baz=$OPTARG ;;
              esac
          done
          shift $((OPTIND - 1))
          bar -t $baz $1 $2 $3
      }
      

      (您可能还想本地化 $baz,而您正在使用它。)

      【讨论】:

        猜你喜欢
        • 2019-05-09
        • 1970-01-01
        • 2015-05-04
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        • 2013-04-17
        • 2012-07-16
        相关资源
        最近更新 更多