bash 使用 getopts 读取一个可选参数并移动正确数量的参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14656181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using getopts to read one optional parameter and shift the right number of arguments
提问by jonderry
I'm writing a simple bash script that takes one optional parameter (-t ) followed by some number of additional arguments.
我正在编写一个简单的 bash 脚本,它带有一个可选参数 (-t),后跟一些附加参数。
I was thinking getopts would be a reasonable way to achieve this, but I'm having difficulty getting the desired behavior. What I have is the following:
我认为 getopts 是实现这一目标的合理方法,但我很难获得所需的行为。我所拥有的是以下内容:
foo() {
baz=10
while getopts ":t:" option; do
case "$option" in
t) baz=$OPTARG ;;
esac
done
shift $((OPTIND - 1))
bar -t $baz
}
The problem is that $OPTINDdoes not seem to vary depending on whether the argument is present, so I don't get the correct behavior as expected with an optional parameter (i.e., I can't get shift to shift the right number of arguments regardless of whether the argument is there).
问题是这$OPTIND似乎并不取决于参数是否存在而变化,所以我没有通过可选参数获得预期的正确行为(即,我无法转移以转移正确数量的参数,无论论据是否存在)。
I want both of the following to execute correctly:
我希望以下两个都正确执行:
foo a b c
foo -t 5 a b c
What's the easiest way to achieve this? I'd prefer a solution that isn't a hack since I may want to use additional optional parameters.
实现这一目标的最简单方法是什么?我更喜欢一个不是黑客的解决方案,因为我可能想使用额外的可选参数。
采纳答案by ruakh
The problem is that you're never resetting $OPTIND, so each time you call fooit examines its arguments starting after the last processed option-index. For example:
问题是您永远不会重置$OPTIND,因此每次调用foo它时都会检查从上次处理的选项索引之后开始的参数。例如:
# $OPTIND is now 1
foo -t opt arg1 arg2 arg3
# the above recognizes -t opt as an option, and sets $OPTIND to 3
# $OPTIND is now 3
foo arg4 arg5 arg6
# the above recognizes that arg6 is not an option, so it leaves $OPTIND at 3
The solution is to localize $OPTINDwithin foo, explicitly setting it to 1:
解决方案是在$OPTIND内进行本地化foo,将其显式设置为1:
foo() {
baz=10
local OPTIND=1
while getopts ":t:" option; do
case "$option" in
t) baz=$OPTARG ;;
esac
done
shift $((OPTIND - 1))
bar -t $baz
}
(You probably want to localize $bazas well, while you're at it.)
(您可能还想进行本地化$baz,同时进行本地化。)
回答by that other guy
It appears that you're trying to write a bash function, not a bash script. OPTIND is set to 1 when the shell/script is invoked, but not when a function is invoked, so subsequent function calls with different arguments would continue parsing at the same point.
看来您正在尝试编写 bash 函数,而不是 bash 脚本。OPTIND 在调用 shell/脚本时设置为 1,但在调用函数时不会设置,因此具有不同参数的后续函数调用将在同一点继续解析。
If you want to keep it as a function, you can reset it manually:
如果你想保留它作为一个函数,你可以手动重置它:
foo() {
OPTIND=1
baz=10
while getopts ":t:" option; do
case "$option" in
t) baz=$OPTARG ;;
esac
done
echo $OPTIND
shift $((OPTIND - 1))
echo bar -t $baz
}

