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前面的注释中:
…
如果
getopt
find另一个选项字符,则返回该字符, 更新optind
和nextchar
以便下次调用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!