我正在使用 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
、 -_
)。 -a
可以是带有选项参数 -a -b
的选项 -a
(恰好看起来像一个选项本身),或者它可以是不同的选项 -b
和 -a
;上述方法将做后者。 要解决这些歧义,您必须坚持使用 with your own approach ,它的缺点是需要提前了解所有可能的传递选项。
关于bash - getopts 能否解析 bash 脚本参数的一个子集,而其余部分保持不变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40088478/