bash - getopts 能否解析 bash 脚本参数的一个子集,而其余部分保持不变?

标签 bash getopts

我正在使用 getopts 来解析 bash 脚本中的参数。我想做两件事:

  • "$@"
  • 中删除已处理的选项
  • "$@"
  • 中保留未处理的选项

    考虑命令行
    $ foo -a val_a -b val_b -c -d -e -f val_f positional_l positional_2 ...
    

    其中 foo 使用 getopts 解析由 'b:c' 的 optstring 定义的选项,然后需要将 "$@" 保留为
    `-a val_a -d -e -f val_f positional_l positional_2 ...`
    

    我需要做两件事:
  • 解析可能给定
  • 的选项子集
  • 保留所有其他选项不变

  • 这是因为 foo 必须使用它识别的选项来确定另一个脚本 bar ,它必须将剩余的 "@" 传递给该脚本。

    通常 getopts 在遇到无法识别的选项时停止,但我需要它继续(直到任何 -- )。我需要它来处理和删除它识别的选项,而不管那些它不知道的选项。

    我确实尝试在 -- 选项和 foo 选项之间使用 bar 来解决我的问题,但是如果 getopts 后面的文本以 -- 开头,- 似乎无法解决(我尝试过但无法转义连字符)。

    无论如何,我不想使用 -- 因为我希望 bar 的存在对 foo 的调用者有效透明,并且我希望 foo 的调用者能够以任何顺序呈现选项。

    我还尝试在 bar 中列出所有 foo 选项(即使用 'a:b:cdef:' 作为 optstring)而不处理它们,但我需要在它们发生时从 "$@" 中删除已处理的选项。我不知道该怎么做( shift 不允许指定位置)。

    我可以手动重建一个新的选项列表(请参阅我自己的答案),但我想知道是否有更好的方法来做到这一点。

    最佳答案

    尝试以下操作,其中 只需要提前知道脚本自己的选项 :

    #!/usr/bin/env bash
    
    passThru=() # init. pass-through array
    while getopts ':cb:' opt; do # look only for *own* options
      case "$opt" in
        b)
          file="$OPTARG";;
        c) ;;
        *) # pass-thru option, possibly followed by an argument
          passThru+=( "-$OPTARG" ) # add to pass-through array
          # see if the next arg is an option, and, if not,
          # add it to the pass-through array and skip it
          if [[ ${@: OPTIND:1} != -* ]]; then
            passThru+=( "${@: OPTIND:1}" )
            (( ++OPTIND ))
          fi
          ;;
      esac
    done
    shift $((OPTIND - 1))
    passThru+=( "$@" )  # append remaining args. (operands), if any
    
    ./"$file" "${passThru[@]}"
    

    注意事项:有两种 歧义无法通过这种方式解决 :
  • 对于带有选项参数的传递选项,此方法仅在参数未直接附加到选项时才有效。
    例如,-a val_a 有效,但 -aval_a 无效(在 a: 参数中没有 getopts 时,这将被解释为一个选项组并将其转换为多个选项 -a-v-a-l-_ )。
  • 正如 chepner 在对该问题的评论中指出的那样, -a 可以是带有选项参数 -a -b 的选项 -a (恰好看起来像一个选项本身),或者它可以是不同的选项 -b-a ;上述方法将做后者。

  • 要解决这些歧义,您必须坚持使用 with your own approach ,它的缺点是需要提前了解所有可能的传递选项。

    关于bash - getopts 能否解析 bash 脚本参数的一个子集,而其余部分保持不变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40088478/

    相关文章:

    php - 为什么这个 shell 脚本没有按预期从 PHP 运行?

    linux - 如何在 bash 末尾使用没有参数的 getopts 选项

    bash - 我如何在 Bash 中解析命令行参数?

    bash - 解析 bash 中的 getopt

    bash - 如何将自定义信号发送到 bash 守护进程?

    Bash 分号等于换行符不完全正确?

    linux - 从文件中提取路径然后将文件复制到另一个路径并将它们重命名为 bash 脚本

    arrays - 根据空行或任何未使用的字符将文本文件拆分为数组

    bash - 阅读 $OPTARG 以获得可选标志?

    java - 在启动脚本中使用 getopts 时丢失 java 主参数