如何处理选项终止—在getopts中


9

我使用getopts将bash脚本中的参数解析为

while getopts ":hd:" opt; do
  case $opt in
    d ) echo "directory = $OPTARG"; mydir="$OPTARG"; shift $((OPTIND-1)); OPTIND=1 ;;
    h ) helptext
      graceful_exit ;;
    * ) usage
      clean_up
      exit 1
  esac
done

exeparams="$*"

exeparams将保留任何未解析的选项/参数。由于我想使用exeparams来保存要在脚本内执行的命令的选项(该选项可以与脚本自己的选项重叠),因此我想使用-结束传递给脚本的选项。如果我通过

myscript -d myscriptparam -- -d internalparam

exeparams 将举行

-- -d internalparam

我现在想删除--将这些参数传递给内部命令的引线。有没有一种优雅的方法可以做到这一点,或者我可以--从getopts中获得仅保留其余部分的字符串?


shift; OPTIND=1getopts循环可能不是这样做的最佳方式。它仅在您的情况下有效,因为您只有2个选项,而在所有其他选项中,仅退出脚本。否则,您将需要shift; OPTIND=1所有选项,这意味着代码重复(错误的做法)。只需shift $((OPTIND - 1))在循环结束后立即执行-这是最传统的方法,也可能是最有效的方法。
2012年

Answers:


7

怎么样:

# ... getopts processing ...

[[ $1 = "--" ]] && shift
exeparams=("$@")

注意,您应该使用数组来保存参数。它将正确处理任何包含空格的参数。解引用数组"${exeparams[@]}"


1
假设options的结尾和之间没有参数--,即script foo -- bar会传递foo -- bar给外部程序。我的回答没有做这个假设,因为问题中没有明确说明。
2012年

除非在OP说:“我现在要删除的龙头 - ”
格伦·杰克曼

那是个例子-- -d internalparams。无论如何,我的回答足以应付任何一种情况。
2012年

14

使用内置的shift。首先,getopts对脚本执行常规操作。该循环完成后,

shift "$((OPTIND - 1))"

将移出所有已处理的选项。

从那里开始,您必须完成对脚本第一部分(在之前--)的非选项参数的处理。一旦你遇到--,转移出来,直到只有后者的部分遗体(在-d internalparam后到来的一部分--)。一种方法(使用bash语法):

while [[ $# -gt 0 ]]; do
    # process next argument
    case $1 in
    foo) # process foo
    ;;
    --) shift; break;; # found '--', discard it and exit loop
    *) # handle unrecognized argument
    ;;
    esac
    # not '--', so discard the argument and continue
    shift
done

最后,仅保留第二组选项/参数,您可以继续传递。千万不要使用$*到其余的参数传递给另一个命令。请"$@"改用,以保留原始单词拆分。

external_command "$@"

对了谢谢!但是我怎么找到--呢?
highsciguy 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.