web-dev-qa-db-ja.com

複数の引数を使用したコマンドラインオプションの解析[getopt?]

コマンドラインからいくつかの引数を取得するには、プログラムが必要です。構文は次のとおりです。

_getpwd -l user1 user2 ... -L -X -S...
_

したがって、ユーザーを_-l_オプションの背後に配置する必要があります。 getoptを使用してみましたが、運が悪かったため、他のオプションを_-l_の前に配置した場合にのみ機能します。

_getpwd -L -X -S ... -l user1 user2 ...
_

私のコード(_-l_および_-S_用):

_    while((c = getopt(argc, argv, "l:S")) != -1){
    switch(c){
        case 'l':
            index = optind-1;
            while(index < argc){
                next = strdup(argv[index]); /* get login */
                index++;
                if(next[0] != '-'){         /* check if optarg is next switch */
                    login[lcount++] = next;
                }
                else break;
            }
            break;
        case 'S':
            sflag++;                        /* other option */
            break;
        case ':':                           /* error - missing operand */
            fprintf(stderr, "Option -%c requires an operand\n", optopt);
            break;
        case '?':                           /* error - unknown option */
            fprintf(stderr,"Unrecognized option: -%c\n", optopt);
            break;
      }
   }
_

optoptoptindは_extern int_です。

したがって、質問は次のとおりです。getopt()関数(またはgetopt_long())を使用できますか?または、必要なものを取得するために独自のパーサーを作成する必要がありますか?

16
Salamander

あなたのコードは実際には非常に、非常に機能に近いものでした。唯一欠けていたのは、getopt-lの後に1つの引数しか消費しないことを想定しているため、-lの最初の引数に続いてコマンドライン解析を続行することです。後戻りしてさらに多くの引数を取り除いているので、コマンドラインの解析を再開する場所をgetoptに指示する必要があります。

getoptは、その情報をグローバル変数optindに格納します。行を追加したとき:

optind = index - 1;

lの場合のbreak;の前に、コードが機能し始めました。

13
rra

コマンドライン引数を解析するためのCライブラリ(GPLライセンス)を作成しました。

https://github.com/Vincenzo1968/myoptParser

https://github.com/Vincenzo1968/myoptParser/blob/master/how_to_use.md

オプションが受け入れる引数の最小数と最大数を指定できます。オプションが0個以上の引数(または1つ以上、2つ以上など)を取るように指定することもできます。そしてもちろん、引数の固定数(0、1、2など)を指定できます。

引数のタイプ(文字列、整数、または浮動小数点数)を指定することもできます。パーサーは、指定された数とタイプが一致することを確認し、一致しない場合はエラーを返します。

パーサーでは、オプションが必要かどうかを指定することもできます。最後に、相互に排他的なオプションを指定できます。

0

次の関数は、引数リスト内の単一のオプションに対してargc、argvのペアを生成します。

void GetArgsList (int argc, char *argv[], int* o_argc, char*** o_argv)
{
    char** ret = NULL;
    int i;
    int count = 0;

    for (i = optind - 1; i < argc ; ++i)
    {
        if (argv[i][0]=='-')
        {
            break;
        }
        else
        {
            if (NULL == ret)
            {
                ret = &argv[i];
            }
            count++;
        }
    }

    optind = i - 1;

    if (o_argc)
    {
        *o_argc = count;
    }

    *o_argv = ret;
}
0
lkanab