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;
}
解決
(=「)等号」。パラメータから任意の引数を分離するスペースが動作しません。
テストコードを実行例
$ ./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 の前にあるコメントの中から:
...
もし
getopt
別のオプション文字を見つけると、その文字を返します。 更新中optind
そしてnextchar
次の電話でgetopt
次のオプション文字またはArgv要素でスキャンを再開できます。オプション文字がなくなった場合は、
getopt
-1 を返します。それからoptind
オプションではない最初のArgv要素のArgvのインデックスです。(Argv-Elementsは、オプションではないものが現在最後に来るように順応しています。)<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted
...
オプトストリングのCHARの後にコロンが続く場合、それはARGが必要なことを意味します。したがって、同じArgv要素の次のテキスト、または次のArgv要素のテキストが返されます。
optarg
. 。2つのコロンは、オプションの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名 "名前" --blame --blame名 "名前"
も動作します。たとえばます:
$ ./respond --blameJohn
You suck John!