【问题标题】:How to allow non-optional arguments to be in front of optional arguments using getopts in Bash?如何在 Bash 中使用 getopts 允许非可选参数位于可选参数前面?
【发布时间】:2014-01-24 11:06:46
【问题描述】:

我知道如何在 Bash 中使用 getopts 处理可选参数

#!/bin/bash

while getopts ":a:p:drh" opt; do
  case "$opt" in
    a) echo $OPTARG;;
  esac
done

但如果我的脚本需要 ./script.sh arg1 [options],我如何告诉 getopts 跳过 arg1?

$ ./script.sh -a 1234
1234
$ ./script.sh arg1 -a 1234
$ ./script.sh arg1
$ ./script.sh -a 1234 arg1
1234

正如我所见,如果将参数放在最后一个位置,我可以处理该参数。我需要在 getopts 中使用什么“正则表达式”才能让我的位置参数位于可选参数之前?

How to allow non-option arguments in any order to getopt? 的建议似乎正在重新排序参数。

【问题讨论】:

    标签: bash getopts


    【解决方案1】:

    如果您知道位置参数的数量,那么您可以执行以下操作:

    #!/bin/bash
    
    VAR=$1
    shift
    echo $VAR
    
    while getopts ":a:p:drh" opt; do
      case "$opt" in
        a) echo $OPTARG;;
      esac
    done
    

    例子:

    > ./test.sh mist -a 2345 -p 45
    mist
    2345
    

    【讨论】:

      【解决方案2】:

      我会这样做。您可以在任何地方放置许多非可选参数。

      #!/bin/bash
      
      while [ $# -gt 0]; do
        while getopts ":a:p:drh" opt; do
          case "$opt" in
            a) echo $OPTARG; shift;;
            p) echo $OPTARG; shift;;
            d) echo Option d;;
            r) echo Option r;;
            h) echo Option h;;
            \?) echo unknown Option;;
            :) echo missing required parameter for Option $OPT;;
          esac
          shift
          OPTIND=1
        done
        if [ $# -gt 0 ]; then
          POSITIONALPARAM=(${POSITIONALPARAM[@]} $1)
          shift
          OPTIND=1
        fi
      done
      
      echo ${POSITIONALPARAM[@]}
      

      内部循环解析参数。每当遇到非选项参数时,它将退出内部循环。外部循环将获取下一个非选项参数。移除非选项参数后,内部循环将被拾取,然后继续读取下一个可选参数,依此类推。

      正如Chrono Kitsune 建议我解释的那样,移位删除第一个参数(可选或不可选)并将所有内容向左移动一个位置。 $1 被删除,$2 变为 $1$3 变为 $2,以此类推。这使脚本可以控制移动非可选参数,直到它变为$1

      shift 和重置OPTIND 都使这成为可能。感谢Chrono Kitsune 建议将 OPTIND 重置为 1 而不是 0。

      ./sample.bash -a one -p two more -d sample

      输出:

      one
      two
      Option d
      more sample
      

      现在让我们使用不同位置的参数调用脚本。

      ./sample.bash more -a one -p two -d sample

      输出:

      one
      two
      Option d
      more sample
      

      【讨论】:

      • OPTIND 应该是 1,而不是 0。注意 shift 的位置可能也是一个好主意,因为它们对于此方法至关重要。
      • OPTIND 可以是 0 或 1,只要它不大于 1。唯一的要求是重置 OPTIND。但是,如果您确实知道有些实现将 OPTIND 设置为 0 不起作用,那么我将不得不开始重置为 1 而不是我习惯的 0。感谢您抽出宝贵时间告诉我。知识就是力量。
      • "如果应用程序将 OPTIND 设置为值 1,则可以使用一组新参数...任何其他调用 getopts 的尝试...将 OPTIND 值修改为除1,产生未指定的结果。” (Source)
      • @Chrono Kitsune - 我将其更新为将 OPTIND 重置为 1 而不是 0。
      • 酷,@alvits。我给了他信用,因为他首先回答,实际上更容易理解,但我确实从你的回答中学到了东西。谢谢。点赞!
      猜你喜欢
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 2016-04-08
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      相关资源
      最近更新 更多