Когда getopt
или getopt_long
встречается с недопустимой опцией, она хранит незаконный символ опции в optopt
. Когда недопустимая опция является долгой опцией, где я могу узнать, какова опция была? И делает что-либо значимое, хранятся в optopt
затем?
Я установил opterr = 0
подавить автоматически печатное сообщение об ошибке. Я хочу создать свое собственное сообщение, что я могу распечатать или зарегистрироваться, где я хотел бы, но я хочу включать название нераспознанной опции.
Самое близкое, что я могу найти, это то, что если вы получите BADCH
, верните элемент argv
, который вызвал его, находится в argv [optind-1]
. Похоже, должен быть лучший способ найти аргумент о проблеме.
Вы совершенно правы в том, что на странице руководства эти детали не указаны, но достаточно подсказок можно почерпнуть из исходного кода, например, реализация glibc в glibc -xyz / posix / getopt.c's _getopt_internal_r
. (Возможно, это единственная интересная реализация этой функции расширения GNU?)
Этот код устанавливает optopt
в 0, когда встречает ошибочную длинную опцию, что, как мне кажется, полезно для того, чтобы отличить этот случай от ошибочного короткого. вариант, когда optopt
обязательно будет отличным от NUL.
Сообщения об ошибках, возникающие при opterr! = 0
, в основном выводят ошибочный длинный параметр как argv [optind]
, а затем код (всегда или - консервативно - по крайней мере в основном) более поздние приращения optind
перед возвратом.
Рассмотрим эту программу:
#include <getopt.h>
#include <stdio.h>
int main(int argc, char **argv) {
struct option longopts[] = {
{ "foo", no_argument, NULL, 'F' },
{ NULL, 0, NULL, 0 }
};
int c;
do {
int curind = optind;
c = getopt_long(argc, argv, "f", longopts, NULL);
switch (c) {
case 'f': printf("-f\n"); break;
case 'F': printf("--foo\n"); break;
case '?':
if (optopt) printf("bad short opt '%c'\n", optopt);
else printf("bad long opt \"%s\"\n", argv[curind]);
break;
case -1:
break;
default:
printf("returned %d\n", c);
break;
}
} while (c != -1);
return 0;
}
$ ./longopt -f -x --bar --foo
-f
./longopt: недопустимая опция - - 'x'
плохой короткий вариант 'x'
./longopt: нераспознанный вариант '--bar'
плохой длинный вариант »- -bar "
--foo
Таким образом, в этих случаях, кэшируя пре- getopt_long
значение optind
, мы легко можем распечатать те же неверные параметры, что и сообщения opterr
.
Это может быть не совсем верно во всех случаях, поскольку использование в реализации glibc собственного __ nextchar
, а не argv [optind]
(в случае «нераспознанной опции») заслуживает учиться, но этого должно быть достаточно, чтобы вы начали.
Если хорошенько подумать о связи между optind
и повторяющимися вызовами getopt_long
, я думаю, что распечатать argv [cached_optind]
будет приятно безопасно. optopt
существует, потому что для коротких опций вам нужно знать, какой именно символ в слове является проблемой, но для длинных опций проблема заключается в целом текущем слове (по модулю исключение аргументов опций из форма = param
).И текущее слово - это то слово, которое getopt_long
просматривает со значением (incoming) optind
.
При отсутствии гарантии, описанной в документации, я был бы несколько менее оптимистичен по поводу использования поведения optopt = 0
.