getopt不parsing参数的可选参数

在C中,getopt_long不parsing命令行参数参数的可选参数。

当我运行该程序时,可选参数不被识别,如下面的示例运行。

$ ./respond --praise John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame You suck ! 

这是testing代码。

 #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; } 

尽pipe在glibc文档或getopt手册页中没有提到,但是对于长型命令行参数的可选参数需要“等号”(=)。 从参数中分隔可选参数的空间不起作用。

以testing代码运行的示例:

 $ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John! 

手册页当然没有很好的logging,但源代码有一点帮助。

简单地说:你应该做下面的事情(虽然这可能有点过度迂腐):

 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前面的注释中:

如果getoptfind另一个选项字符,则返回该字符, 更新optindnextchar以便下次调用getopt可以使用以下选项字符或ARGV-element恢复扫描。

如果没有更多选项字符,则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; } 

我也遇到了同样的问题,来到这里。 然后我意识到这一点。 你没有太多的“optional_argument”的用例。 如果需要一个选项,你可以从程序逻辑中检查,如果一个选项是可选的,那么你不需要做任何事情,因为在getopt级别,所有选项都是可选的,它们不是强制的,所以没有使用“optional_argument”的情况。 希望这可以帮助。

ps:对于上面的例子,我认为正确的选项是–praise –praise-name“name”–blame –blame-name“name”

如果你在没有空格字符的参数旁边input参数,那么这两个参数都不起作用。 例如:

 $ ./respond --blameJohn You suck John!