Подтвердить что ты не робот

Разбор параметров командной строки с несколькими аргументами [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;
      }
   }

optopt и optind являются extern int.

Итак, возникает вопрос: могу ли я использовать функцию getopt() (или getopt_long())? Или мне нужно написать собственный парсер, чтобы получить то, что мне нужно?

4b9b3361

Ответ 1

Ваш код действительно был очень, очень близок к работе. Единственное, чего вам не хватало, - это то, что getopt ожидает, что вы будете использовать один аргумент после -l и, следовательно, продолжите разбор строки в командной строке после первого аргумента -l. Поскольку вы идете за его спину и вытягиваете больше аргументов, вы должны сказать getopt, где снова начать синтаксический анализ командной строки.

getopt хранит эту информацию в глобальной переменной optind. Когда я добавил строку:

optind = index - 1;

до break; в вашем случае l, ваш код начал работать.

Ответ 2

Я написал библиотеку C (лицензию GPL) для анализа аргументов командной строки:

https://github.com/Vincenzo1968/myoptParser

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

Вы можете указать минимальное и максимальное количество аргументов, которые принимает данный параметр. Вы также можете указать, что параметр принимает ноль или более аргументов (или один или несколько, два или более и т.д.). И, конечно же, вы можете указать фиксированное количество аргументов: ноль, один, два и т.д.

Вы также можете указать тип аргументов: string, integer или float. Парсер проверяет соответствие указанных номеров и типов и, в противном случае, возвращает ошибку.

Парсер также позволяет указать, требуется ли опция или нет. Вы можете, наконец, указать взаимоисключающие опции.

Ответ 3

Следующая функция сгенерирует пару 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;
}