getopt()
возвращает ' :
'. Если первый символ optstring
не является двоеточием, getopt()
возвращает ' ?
', делая этот случай неотличимым от случая неверной опции.
Таким образом, помещение в качестве первого символа optstring
двоеточия является хорошей мыслью, поскольку это позволяет различать «неверную опцию» и «отсутствующий аргумент опции». Расплатой за это является то, что getopt()
в этом случае также не предпринимает никаких действий, заставляя вас выводить собственные сообщения об ошибках. Вот предыдущий пример, на этот раз с обработкой ошибок:
int ос; /* символ опции */
char *b_opt_arg;
while ((ос = getopt(argc, argv, ":ab:")) != -1) {
switch (oc) {
case 'a':
/* обработка -a, установка соответствующего флага */
break;
case 'b':
/* обработка -b, получение значения аргумента из optarg */
b_opt_arg = optarg;
break;
case ':':
/* отсутствует аргумент опции */
fprintf(stderr, "%s: option '-%c' requires an argument\n",
argv[0], optopt);
break;
case '?':
default:
/* недействительная опция */
fprintf(stderr, "%s: option '-%c' is invalid: ignored\n",
argv[0], optopt);
break;
}
}
Замечание о соглашениях по именованию флагов или опций: в большом количестве кода для Unix используются имена в виде xflg
для любого данного символа опции x (например, nflg
в echo
V7; обычным является также xflag
). Это может быть замечательным для авторе программы, который без проверки документации знает, что означает опция x . Но это не подходит для кого-то еще, кто пытается прочесть код и не знает наизусть значений всех символов опций. Гораздо лучше использовать имена, передающие смысл опции, как no_newline
для опции -n
echo.
2.3.2. GNU getopt()
и порядок опций
Стандартная функция getopt()
прекращает поиск опций, как только встречает аргумент командной строки, который не начинается с GNU getopt()
отличается: она просматривает в поисках опций всю командную строку. По мере продвижения она переставляет элементы argv
, так что после ее завершения все опции оказываются переставленными в начало, и код, продолжающий разбирать аргументы с argv[optind]
до argv[argc-1]
, работает правильно. Во всех случаях специальный аргумент ' --
' завершает сканирование опций.
Вы можете изменить поведение по умолчанию, использовав в optstring
специальный первый символ следующим образом:
optstring[0] == '+'
GNU getopt()
ведет себя, как стандартная getopt()
; она возвращает опции по мере их обнаружения, останавливаясь на первом аргументе, не являющемся опцией. Это работает также в том случае, если в окружении присутствует строка POSIXLY_CORRECT
.
optstring[0] == '-'
GNU getopt()
возвращает каждый аргумент командной строки независимо от того, представляет он аргумент или нет. В этом случае для каждого такого аргумента функция возвращает целое 1, а указатель на соответствующую строку помещает в optarg
.
Как и для стандартной getopt()
, если первым символом optstring
является ' :
', GNU getopt()
различает «неверную опцию» и «отсутствующий аргумент опции», возвращая соответственно ' ?
' или ' :
'. Символ ' :
' в optstring
может быть вторым символом, если первым символом является ' +
' или ' -
'.
Наконец, если за символом опции в optstring
следуют два двоеточия, эта опция может иметь необязательный аргумент. (Быстро повторите это три раза!) Такой аргумент считается присутствующим, если он находится в том же элементе argv
, что и сама опция, и отсутствующим в противном случае. В случае отсутствия аргумента GNU getopt()
возвращает символ опции, а в optarg
записывает NULL. Например, пусть имеем:
while ((с = getopt(argc, argv, "ab::")) != -1)
...
для -bYANKEES
, возвращаемое значение будет ' b
', a optarg
указывает на « YANKEES
», тогда как для -b
или ' -b YANKEES
' возвращаемое значение будет все то же ' b
', но в optarg
будет помещен NULL. В последнем случае « YANKEES
» представляет отдельный аргумент командной строки.
Функция getopt_long()
осуществляет разбор длинных опций в описанном ранее виде. Дополнительная процедура getopt_long_only()
работает идентичным образом, но она используется для программ, в которых все опции являются длинными и начинаются с единичного символа ' -
'. В остальных случаях обе функции работают точно так же, как более простая функция GNU getopt()
. (Для краткости, везде, где мы говорим « getopt_long()
», можно было бы сказать « getopt_long()
и getopt_long_only()
».) Вот объявления функций из справки getopt(3) GNU/Linux:
Читать дальше