getOpt는 옵션 인수를 매개 변수에 구문 분석하지 않습니다
-
20-08-2019 - |
문제
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;
}
해결책
GLIBC 문서 또는 GetOpt Man 페이지에는 언급되지 않았지만 긴 스타일 명령 줄 매개 변수에 대한 선택적 인수는 'Equals Sign'(=)을 요구합니다. 옵션 인수를 매개 변수에서 분리하는 공간은 작동하지 않습니다.
테스트 코드에서 실행되는 예제 :
$ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John!
다른 팁
Man Page는 확실히 잘 문서화하지 않지만 소스 코드는 약간 도움이됩니다.
간단히 : 당신은 다음과 같은 일을해야합니다 (이것은 약간 과장된 것일 수 있지만) :
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-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-element의 텍스트가 반환됩니다.
optarg
. 두 개의 콜론은 옵션 인 Arg를 원하는 옵션을 의미합니다. 현재 ARGV 요소에 텍스트가 있으면 반환됩니다.optarg
, 그렇지 않으면optarg
0으로 설정됩니다....
... 라인 사이를 읽어야하지만. 다음은 원하는 것을 수행합니다.
#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;
}
나는 또한 같은 문제에 부딪쳐서 여기에왔다. 그런 다음 이것을 깨달았습니다. "옵션 _argument"의 사용 사례가 많지 않습니다. 옵션이 필요한 경우 프로그램 로직에서 확인하면 옵션이 선택 사항 인 경우 GetOpt 레벨에서 모든 옵션이 선택 사항이므로 필수가 아니므로 "옵션 _argument"의 사용 사례가 없습니다. 도움이 되었기를 바랍니다.
PS : 위의 예에서는 올바른 옵션이 -praise -praise-name "name"-Blame-Name "Name"이라고 생각합니다.
공간 문자가없는 매개 변수 옆에 인수를 작성하면 동등한도 작동하지 않습니다. 예를 들어:
$ ./respond --blameJohn
You suck John!