我使用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
不允许指定位置。)
我可以手动重建一个新的选项列表(参见我自己的答案),但我想知道是否有更好的方法来做到这一点。
答案 0 :(得分:3)
您可以手动重建选项列表,例如此示例处理-b
和-c
选项并传递任何未完整的内容。
#!/bin/bash
while getopts ":a:b:cdef:" opt
do
case "${opt}" in
b) file="$OPTARG" ;;
c) ;;
*) opts+=("-${opt}"); [[ -n "$OPTARG" ]] && opts+=("$OPTARG") ;;
esac
done
shift "$((OPTIND-1))"
./$file "${opts[@]}" "$@"
所以
./foo -a 'foo bar' -b bar -c -d -e -f baz one two 'three and four' five
将调用bar
作为选项b
的参数,作为
./bar -a 'foo bar' -d -e -f baz one two 'three and four' five
此解决方案的缺点是 optstring 必须包含传递选项(即":a:b:cdef:"
而不是优先":b:c"
)。
用重建的参数列表替换参数列表可以这样做:
set -- "${opts[@]}" "$@"
将使"$@"
包含问题中指定的未处理参数。
答案 1 :(得分:2)
请尝试以下操作,只需要提前知道脚本拥有选项:
#!/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[@]}"
警告:有两种类型的歧义无法以这种方式解决:
对于带有选项参数的pass-thru选项,此方法仅在参数不是 直接附加到选项时才有效。 />
例如,-a val_a
有效,但-aval_a
不会{在a:
参数中没有getopts
,这将被解释为选项组并将其转换为多个选项-a
,-v
,-a
,-l
,-_
,-a
)。
正如chepner在对该问题的评论中指出的那样,-a -b
可以是带有选项参数-a
的选项-b
(恰好看起来像一个选项本身),或者它可以是不同的选项-a
和-b
;上述方法将采用后者。
要解决这些含糊之处,你必须坚持with your own approach,它必须提前知道所有可能的直通选项。