bash 没有 cmd 时 getopts 打印帮助。行参数匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9804502/
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
getopts printing help when no cmd. line argument was matched
提问by Tomas Pruzina
I'm trying to use getopts in bash to parse command line arguments, but I couldn't figure out how to implement "default" action, if no argument was matched (or no cmdline argument given).
我试图在 bash 中使用 getopts 来解析命令行参数,但如果没有匹配的参数(或没有给出 cmdline 参数),我无法弄清楚如何实现“默认”操作。
This is silghtly simplified version of what I've tried so far:
这是我迄今为止尝试过的略有简化的版本:
while getopts v:t:r:s:c: name;
do
case $name in
v) VALIDATE=1;;
t) TEST=1;;
r) REPORT=1;;
s) SYNC=1;;
c) CLEAR=1;;
*) print_help; exit 2;;
\?) print_help; exit 2;;
esac
done
Is there any (simple) way to make it call print_help; exit 2; on non matching input?
有什么(简单的)方法可以让它调用 print_help; 出口2;在不匹配的输入上?
采纳答案by David Souther
Looking between your question and the comments on Aditya's answer, I'd recommend the following:
在您的问题和对 Aditya 回答的评论之间,我建议如下:
[getopts]$ cat go
#!/bin/bash
function print_help { echo "Usage" >&2 ; }
while getopts vtrsc name; do
case $name in
v) VALIDATE=1;;
t) TEST=1;;
r) REPORT=1;;
s) SYNC=1;;
c) CLEAR=1;;
?) print_help; exit 2;;
esac
done
echo "OPTIND: $OPTIND"
echo ${#@}
shift $((OPTIND - 1))
while (( "$#" )); do
if [[ == -* ]] ; then
echo "All opts up front, please." >&2 ; print_help ; exit 2
fi
echo
shift
done
Since each of those are boolean flag options, you don't need (and in fact, do not want) the arguments, so we get rid of the colons. None of those characters are in IFS, so we don't need to wrap that in quotes, it will be one token for getopts anyway.
由于每个都是布尔标志选项,您不需要(实际上也不想要)参数,因此我们去掉了冒号。这些字符都不在 IFS 中,因此我们不需要将其用引号括起来,无论如何它都是 getopts 的一个标记。
Next, we change the \?to a single ?and get rid of the *, as the *would match before the literal \?, and we might as well combine the rules into a single default match. This is a good thing, since any option specified with a -prefix should be an option, and users will expect the program to fail if they specify an option you don't expect.
接下来,我们将 the 更改\?为单个?并去掉*, 因为 the*会在文字 之前匹配\?,我们不妨将这些规则组合成一个默认匹配。这是一件好事,因为任何用-前缀指定的选项都应该是一个选项,如果用户指定了一个你不期望的选项,他们会期望程序失败。
getoptswill parse up to the first thing that isn't an argument, and set OPTINDto that position's value. In this case, we'll shift OPTIND - 1(since opts are 0-indexed) off the front. We'll then loop through those args by shifting them off, echoing them or failing if they start with a -.
getopts将解析到不是参数的第一件事,并设置OPTIND为该位置的值。在这种情况下,我们将OPTIND - 1移到前面(因为 opts 是 0 索引的)。然后,我们将通过将它们移开、回显或失败(如果它们以-.
And to test:
并测试:
[getopts]$ ./go
OPTIND: 1
0
[getopts]$ ./go -t -v go go
OPTIND: 3
4
go
go
[getopts]$ ./go -d -v go go
./go: illegal option -- d
Usage
[getopts]$ ./go -t go -v go -d
OPTIND: 2
5
go
All opts up front, please.
Usage
回答by kenorb
Try the following workaround:
尝试以下解决方法:
# Parse the arguments.
while getopts ':h?f:' opts; do
case ${opts} in
f) # Foo argument.
;;
# My other arguments.
\? | h | *) # Prints help.
grep " .)\ #" "v:t:r:s:c:"
exit 0
;;
esac
done
So basically -?/-hwould print the parameters with comments based on its own source. Specifying :before options will print help for any other unknown argument also.
所以基本上-?/-h会根据自己的来源打印带有注释的参数。:在选项之前指定也将打印任何其他未知参数的帮助。
回答by Aditya Naidu
v:t:r:s:c:should be in double quotes
v:t:r:s:c:应该是双引号
Based on the script you posted, maybe you don't require all those colons :
根据您发布的脚本,也许您不需要所有这些冒号 :
Also you don't need *)
你也不需要 *)
回答by glenn Hymanman
You need to provide a leading colon in the getopts option string if you want to enable ?to match an invalid option -- :vtrsc. Also you don't need the backslash before the ?
如果要启用?以匹配无效选项 -- ,则需要在 getopts 选项字符串中提供前导冒号:vtrsc。你也不需要在之前的反斜杠?

