getopt는 선택적 인수를 매개 변수로 해석하지 않습니다.
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 페이지에는 언급되지 않지만 긴 스타일의 명령줄 매개 변수를 위한 선택적 인수에는 '부호'(=)가 필요합니다.선택적 인수와 매개 변수를 구분하는 공간은 작동하지 않습니다.
테스트 코드를 사용하여 실행하는 예:
$ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John!
man 페이지는 확실히 잘 문서화되어 있지 않지만, 소스코드가 조금 도움이 됩니다.
간단히: 다음과 같은 작업을 수행해야 합니다(단, 이는 좀 지나친 정신지체일 수 있습니다).
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 앞의 코멘트 중:
...
if
getopt
다른 옵션 문자를 찾으면 해당 문자가 반환되고 업데이트 및nextchar
을 할 수getopt
는, 다음의 또는 를 할 수 ., 「」를 참조해 주세요.
getopt
1을 반환합니다. ★★★★★★★★★★★★★★★.optind
ARGV의 ARGV의 ARGV의 ARGV의 ARGV의 ARGV의 의 Elements (가 마지막에.)(ARGV 요소는 옵션이 아닌 요소가 마지막에 오도록 배열되어 있습니다).<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted
...
콜론이 붙어 있는 ARGV 또는 는 OPTSTRING으로 됩니다.
optarg
. arg를 로 하는 ARGV로 반환됩니다.현재 ARGV 요소에 텍스트가 있는 경우 다음 형식으로 반환됩니다.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[optind]
&& '-' != argv[optind][0] ) {
// This is what makes it work; if `optarg` isn't set
// and argv[optind] doesn't look like another option,
// then assume it's our parameter and overtly modify optind
// 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`, `optind`, etc, and they're
// not marked const -- implying they expect and intend you
// to modify them if needed.
tmp_optarg = argv[optind++];
}
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;
}
나는 최근에 이 문제를 직접 접했다.Brian Vandenberg와 Haystack이 제안한 것과 유사한 해결책을 찾았습니다.그러나 가독성을 향상시키고 코드 중복을 피하기 위해 다음과 같은 매크로로 모든 내용을 정리할 수 있습니다.
#define OPTIONAL_ARGUMENT_IS_PRESENT \
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
? (bool) (optarg = argv[optind++]) \
: (optarg != NULL))
매크로는 다음과 같이 사용할 수 있습니다.
case 'o': // option with optional argument
if (OPTIONAL_ARGUMENT_IS_PRESENT)
{
// Handle is present
}
else
{
// Handle is not present
}
break;
이 솔루션의 구조에 대한 자세한 내용은 블로그 투고(https://cfengine.com/blog/2021/optional-arguments-with-getopt-long/를 참조해 주십시오.
이 솔루션은 테스트되고 있으며, 현재 CFEngine에서 사용되고 있습니다.
저도 같은 문제에 부딪혀 왔어요.그리고 나는 이것을 깨달았다."optional_argument"의 사용 사례는 많지 않습니다.옵션이 필요한 경우 프로그램 로직에서 체크하고 옵션이 옵션인 경우 getopt 수준에서는 모든 옵션이 옵션이기 때문에 아무것도 할 필요가 없습니다.따라서 "optional_argument"의 사용 사례는 없습니다.이게 도움이 됐으면 좋겠다.
ps: 위의 예에서 올바른 옵션은 --syslog --syslog-name "name" --syslog --syslog-name "name" 입니다.
언급URL : https://stackoverflow.com/questions/1052746/getopt-does-not-parse-optional-arguments-to-parameters
'programing' 카테고리의 다른 글
vue.js가 사이트 또는 웹 앱에서 사용되는지 확인하는 방법 (0) | 2022.07.09 |
---|---|
어레이 복사 (0) | 2022.07.09 |
루트 파라미터 vuej에 따라 컴포넌트/템플릿 로드 (0) | 2022.07.09 |
Vue.js - Enter 키를 사용하여 양식을 제출하려면 어떻게 해야 합니까? (0) | 2022.07.09 |
Firebase 및 VueJ: 미포함(예약) DOMException:원본이 "http://localhost:3000"인 프레임을 차단했습니다. (0) | 2022.07.05 |