Разбор параметров командной строки с несколькими аргументами [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()
)? Или мне нужно написать собственный парсер, чтобы получить то, что мне нужно?
Ответы
Ответ 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;
}