1

このコマンドのオプションを取得したい:

my_cmd show --value true -D

それを取得するには、オプションを 2 回実行する必要があります (アーキテクチャのため)。2 番目のパスでは、そのオプションに対応する引数を正しく取得することはできません。この例では、2 番目のパスで取得された (オプションの--value) 引数は-Dではなく ですtrue

最初のパス:

void getoptions (int argc, char **argv, globalargs_t* globalargs) {

    static const char *optstring = "vDqnd:c:f:o:h?:";

    static const struct option longopts[] = {
        { "help",         no_argument,        NULL,    'h' },
        { "Debug",        no_argument,        NULL,    'D'},
        { "verbose",    no_argument,        NULL,    'v'},
        { "quiet",        no_argument,        NULL,    'q'},
        { "noheader",    no_argument,        NULL,    0},
        { "delimiter",    required_argument,     NULL,    0},
        { "columns",    required_argument,    NULL,    0},
        { "filter",        required_argument,    NULL,    0},
        { "order",        required_argument,    NULL,    0},
        { "getid",        no_argument,        NULL,    'i'},
        { NULL,            no_argument,        NULL,    0 }
    };

    int opt = 0;
    int longindex = 0;
    //opterr = 0;

    /* Process the arguments with getopt_long(), then populate globalargs-> */
    opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    while( opt != -1 ) {
        switch( opt ) {
            case '?':
                break;
            case 'D':
                globalargs->debug = 1;    /* true */
                break;
            case 'v':
                globalargs->verbose++;
                break;
            case 'q':
                globalargs->quiet = 1;
                break;
            case 'i':
                globalargs->id = 1;
                break;
            case 'h':
                globalargs->help = 1;
                break;
            case 0:        /* long option without a short arg */
                if( strcmp( "Debug", longopts[longindex].name ) == 0 ) {
                    globalargs->debug = 1;
                }
                if( strcmp( "verbose", longopts[longindex].name ) == 0 ) {
                    globalargs->verbose = 1;
                }
                if( strcmp( "quiet", longopts[longindex].name ) == 0 ) {
                    globalargs->quiet = 1;
                }
                if( strcmp( "noheader", longopts[longindex].name ) == 0 ) {
                    globalargs->noheader = 1;
                }
                if( strcmp( "delimiter", longopts[longindex].name ) == 0 ) {
                    globalargs->delimiter = *optarg;
                }
                if( strcmp( "filter", longopts[longindex].name ) == 0 ) {
                    globalargs->filter = optarg;
                }
                if( strcmp( "order", longopts[longindex].name ) == 0 ) {
                    globalargs->order = optarg;
                }
                if( strcmp( "columns", longopts[longindex].name ) == 0 ) {
                    globalargs->columns = optarg;
                }
                break;
            default:
                /* You won't actually get here. */
                break;
        }
        opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    }
    if (optind < argc) {
        while (optind < argc) {
            globalargs->actions[globalargs->actionsindex] = argv[optind++];
            globalargs->actionsindex++;
        }
    }
}

2 番目のパス:

void getspecificoptions(int argc, char **argv, globalargs_t* globalargs) {
    static const char *optstring = ":n:d:v:d";

    static const struct option longopts[] = {
        { "name",                required_argument,     NULL,    'n'},
        { "domain",                required_argument,    NULL,    0},
        { "value",                required_argument,    NULL,    0},
        { "defined_value",        required_argument,    NULL,    0},
        { NULL,                    no_argument,        NULL,    0 }
    };

    optind = 1;
    int opt = 0;
    int longindex = 0;

    /* Process the arguments with getopt_long(), then populate globalargs-> */
    opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    while( opt != -1 ) {
        switch( opt ) {
            case 'n':
                /* If used in update/add => must be still a filter */
                globalargs->filter = strcat(globalargs->filter,"cluster.name=");
                globalargs->filter = strcat(globalargs->filter, optarg);
                if(!globalargs->table || strcmp(globalargs->table, "cluster") == 0 ) {
                    globalargs->table = "cluster";
                }
                else {
                    clmError(&t, "dbm-command", -1, "Incompatible options.");
                    exit(EXIT_FAILURE_OPTIONS);
                }
                break;
            case 0:        /* long option without a short arg */
                if( strcmp( "domain", longopts[longindex].name ) == 0 ) {

                    }
                    else {
                        char* f = my_new(500*sizeof(char));
                        f = strcat(f, "cluster.dns_domain=");
                        f = strcat(f, optarg);
                        globalargs->actions[globalargs->actionsindex] = f;
                        globalargs->actionsindex++;
                    }
                    if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "cluster") == 0 ) {
                        globalargs->table = "cluster";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                if( strcmp( "value", longopts[longindex].name ) == 0 ) {
                    if(strcmp(globalargs->actions[0], "show") == 0 || strcmp(globalargs->actions[0], "delete") == 0 ) {
                        globalargs->filter = realloc(globalargs->filter, strlen(globalargs->filter) + strlen(optarg) + strlen("cluster_profile.value=") + 1);
                        globalargs->filter = strcat(globalargs->filter,"cluster_profile.value=");
                        globalargs->filter = strcat(globalargs->filter, optarg);
                    }
                    else {
                        char* act = my_new(strlen(optarg) + strlen("cluster_profile.value=") + 1U);
                        act = strcat(act, "cluster_profile.value=");
                        act = strcat(act, optarg);
                        globalargs->actions[globalargs->actionsindex] = act;
                        globalargs->actionsindex++;
                    }
                    if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "profile") == 0 ) {
                        globalargs->table = "profile";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                if( strcmp( "defined_value", longopts[longindex].name ) == 0 ) {
                    /* If used in update/add => must be still a filter */
                    globalargs->filter = strcat(globalargs->filter,"cluster_profile.defined_value=");
                    globalargs->filter = strcat(globalargs->filter, optarg);

                    if(!globalargs->table || strcmp(globalargs->table, "profile") == 0 ) {
                        globalargs->table = "profile";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                break;
        }
        opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    }
}

これらのパスの後、私はglobalargs->filter="-D".

どんな助けでも大歓迎です。

ありがとうございました!

4

2 に答える 2

2

optind は 1 ではなく 0 にリセットする必要があります。初回は修飾フラグが解析されますが、2 回目は解析されません。なぜなら、optind は 0 ではなく 1 であるためです。0 に設定すると、文字列が再解析されます。

引数が並べ替えられないように、optstring の最初の文字も + または - (先頭のコロンの前) にする必要があります。

これはすべて、GNU の getopt_long を使用していることを前提としています。

于 2012-08-08T15:42:00.863 に答える
1

getoptマニュアルで説明されているように、引数を並べ替え、すべての非オプション引数の前にすべてのオプション引数を返します。

デフォルトでは、getopt()はスキャン時に argv の内容を並べ替え、最終的にすべての非オプションが end になるようにします。他にも 2 つのモードが実装されています。optstring の最初の文字が「+」であるか、環境変数 POSIXLY_CORRECT が設定されている場合、オプション以外の引数が検出されるとすぐにオプション処理が停止します。optstring の最初の文字が「-」の場合、オプション以外の各 argv 要素は、文字コード 1 のオプションの引数であるかのように処理されます。特別な引数 "--" は、スキャン モードに関係なく、オプション スキャンを強制的に終了させます。

の適切な長い構文は--value trueisであるため--value=truetrueは非オプション引数として扱われ、オプション引数の後ろにシフトされます。

于 2012-08-08T15:39:18.327 に答える