在C中,getopt_long不会解析命令行参数参数的可选参数。
当我运行程序时,无法识别可选参数,如下面的示例运行。
$ ./respond --praise John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame
You suck !
这是测试代码。
#include <stdio.h>
#include <getopt.h>
int main(int argc, char ** argv )
{
int getopt_ret, option_index;
static struct option long_options[] = {
{"praise", required_argument, 0, 'p'},
{"blame", optional_argument, 0, 'b'},
{0, 0, 0, 0} };
while (1) {
getopt_ret = getopt_long( argc, argv, "p:b::",
long_options, &option_index);
if (getopt_ret == -1) break;
switch(getopt_ret)
{
case 0: break;
case 'p':
printf("Kudos to %s\n", optarg); break;
case 'b':
printf("You suck ");
if (optarg)
printf (", %s!\n", optarg);
else
printf ("!\n", optarg);
break;
case '?':
printf("Unknown option\n"); break;
}
}
return 0;
}
答案 0 :(得分:83)
虽然glibc文档或getopt手册页中没有提到,但长样式命令行参数的可选参数需要'等号'(=)。将可选参数与参数分开的空格不起作用。
运行测试代码的示例:
$ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John!
答案 1 :(得分:15)
手册页肯定没有很好地记录,但源代码有点帮助。
简单地说:你应该做类似下面的事情(尽管这可能有点过于迂腐):
if( !optarg
&& optind < argc // make sure optind is valid
&& NULL != argv[optind] // make sure it's not a null string
&& '\0' != argv[optind][0] // ... or an empty string
&& '-' != argv[optind][0] // ... or another option
) {
// update optind so the next getopt_long invocation skips argv[optind]
my_optarg = argv[optind++];
}
/* ... */
来自_getopt_internal之前的评论:
...
如果
getopt
找到另一个选项字符,则返回该字符, 更新optind
和nextchar
,以便下次调用getopt
即可 使用以下选项字符或ARGV元素恢复扫描。如果没有其他选项字符,
getopt
将返回-1。 然后optind
是第一个ARGV元素的ARGV中的索引 这不是一个选择。 (ARGV元素已被置换 所以那些不是选项的人现在最后。)<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted
...
如果OPTSTRING中的一个字符后面跟一个冒号,那就意味着它需要一个arg, 所以下面的文字在同一个ARGV元素中,或者下面的文字 ARGV元素在
optarg
中返回。两个冒号意味着一个选项 想要一个可选的arg;如果当前ARGV元素中有文本, 它在optarg
中返回,,否则optarg
设置为零。...
......虽然你必须在两行之间做一些阅读。以下是您想要的:
#include <stdio.h>
#include <getopt.h>
int main(int argc, char* argv[] ) {
int getopt_ret;
int option_index;
static struct option long_options[] = {
{"praise", required_argument, 0, 'p'}
, {"blame", optional_argument, 0, 'b'}
, {0, 0, 0, 0}
};
while( -1 != ( getopt_ret = getopt_long( argc
, argv
, "p:b::"
, long_options
, &option_index) ) ) {
const char *tmp_optarg = optarg;
switch( getopt_ret ) {
case 0: break;
case 1:
// handle non-option arguments here if you put a `-`
// at the beginning of getopt_long's 3rd argument
break;
case 'p':
printf("Kudos to %s\n", optarg); break;
case 'b':
if( !optarg
&& NULL != argv[optindex]
&& '-' != argv[optindex][0] ) {
// This is what makes it work; if `optarg` isn't set
// and argv[optindex] doesn't look like another option,
// then assume it's our parameter and overtly modify optindex
// to compensate.
//
// I'm not terribly fond of how this is done in the getopt
// API, but if you look at the man page it documents the
// existence of `optarg`, `optindex`, etc, and they're
// not marked const -- implying they expect and intend you
// to modify them if needed.
tmp_optarg = argv[optindex++];
}
printf( "You suck" );
if (tmp_optarg) {
printf (", %s!\n", tmp_optarg);
} else {
printf ("!\n");
}
break;
case '?':
printf("Unknown option\n");
break;
default:
printf( "Unknown: getopt_ret == %d\n", getopt_ret );
break;
}
}
return 0;
}
答案 2 :(得分:1)
我也遇到了同样的问题来到这里。然后我意识到这一点。 你没有太多的&#34; optional_argument&#34; 。如果需要一个选项,你可以从程序逻辑中检查,如果一个选项是可选的,那么你不需要做任何事情,因为在getopt级别所有选项都是可选的,它们不是强制性的,所以没有&#34; optional_argument&#34的用例;。希望这会有所帮助。
ps:对于上面的例子,我认为正确的选择是 --praise --praise-name&#34; name&#34; --blame --blame-name&#34; name&#34;
答案 3 :(得分:-4)
如果在没有空格字符的参数旁边写入参数,则两者也不起作用。例如:
$ ./respond --blameJohn
You suck John!