getopt порядок argv при передаче нескольких аргументов в одну опцию - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь передать несколько аргументов одному варианту. Например,

(1) ./someProgram -f opt1 opt2 opt3 -j opt -d.

(2) ./someProgram -f /dir/dir/* -j opt -d.

Мои настройки для getopt_long выглядят следующим образом.

const char *short_opt = "hp:j:o:f:";
    struct option long_opt[] =
            {
                    {"help",      no_argument,       NULL, 'h'},
                    {"journal",   required_argument, NULL, 'j'},
                    {"partition", required_argument, NULL, 'p'},
                    {"output",    required_argument, NULL, 'o'},
                    {"file",      required_argument, NULL, 'f'},
                    {NULL, 0,                        NULL, 0}
            };

Я попытался упростить основной код, чтобы он не выглядел подавляющим. Я оставил части, где я взаимодействую с переменными getopt_long.

while ((arg = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
        switch (arg) {
            case -1:
            case 0:        
                break;
            ...
            case 'j':
                if (optarg) {
                    setSomeVar; //And nothing else, only set var and break.
                }
                break;
            case 'f':
                if (optarg) {
                    index = optind - 1;
                    while (index < argc) {
                        nextOpt = strdup(argv[index]);
                        index++;
                        if (nextOpt[0] != '-') {
                            callFunc(nextOpt);
                        }
                        else {
                            break;
                        }
                    }
                    optind = index - 1;
                }
                else {
                    fprintf(stderr, "...\n");
                    exit(EXIT_FAILURE);
                }
                break;
            case ':':
            case '?':
                fprintf(stderr, "...");
                return (EXIT_FAILURE);

            default:
                fprintf(stderr, "...", argv[0], arg);
                return (EXIT_FAILURE);
        };

Если я назову свою программу, как показано ниже, все будет как положено.

Первый ввод

./prog -f /dir/dir/* - (60 files) or ./prog -f file1 file2 file3
info about file1
info about file2
... and so on

Если я добавлю еще один параметр в конец.

Второй ввод

./prog -f file1 file2 file3 file4 -j smth
info about1 file1
action with -j smth. **End.**

Я попытался перечислить все аргументы в начале, с второй вход примерно так:

for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
}

И результат был ожидаемым (для второго ввода)

-f, file1,file... -j,print

Опять я включил это для l oop в моем переключатель, под 'F' случае. И используя второй вход, я увидел, что аргумент alredy 3 был -j, а 4-й был опцией для j, и только после этого были все остальные файлы. Вывод был, как вы уже можете догадаться,

file1, -j, print, file2, file3,file4

Мой вопрос: почему это происходит? Или как мне это исправить, или мне нужно было посмотреть? Также я попытался улучшить свой код, глядя на несколько похожих вопросов, на которые здесь даны ответы, но похоже, что я уже следую всем советам.

Анализ параметров командной строки с несколькими аргументами [getopt?]

C получение нескольких значений

Получить несколько значений для одной и той же опции [duplicate]

Решение путем передачи всех аргументов в кавычках, не работает для меня, потому что пользователь может захотеть перенаправить ввод из ls, например, или передать directrory с * в конце.

Спасибо:)

1 Ответ

0 голосов
/ 29 апреля 2020

Это примерно шестой абзац в man getopt (для версии Gnu, которую вы явно используете):

По умолчанию getopt () переставляет содержимое argv при сканировании, так что в конце концов все неопции в конце. Два других режима также реализованы. Если первый символ строки optstring равен «+» или установлена ​​переменная окружения POSIXLY_CORRECT, тогда обработка опции останавливается, как только встречается аргумент без опции. Если первый символ строки optstring равен «-», то каждый необязательный argv-элемент обрабатывается так, как если бы он был аргументом опции с символьным кодом 1. (Это используется программами, которые были написаны для ожидания опций и других argv-элементов в любом порядке, и это заботит порядок двух.) Специальный аргумент "-" принудительно завершает сканирование опций независимо от режима сканирования.

Я думаю, что вы могли бы сделать ваш код работает с использованием любого из режимов не по умолчанию, но я бы go со стандартным Posix для переносимости.

(Хотя на самом деле я бы рекомендовал вам не использовать нестандартное соглашение об аргументах утилит. Параметры должны принимать один аргумент; достаточно просто повторить параметр над списком, если вы этого хотите.)

...