4. Аргументы опции отделяются от длинных опций либо разделителем, либо символом
=
. Например,
– -sourcefile=/some/file
или
– -sourcefile /some/file
.
5. Опции и аргументы могут быть заинтересованы в операндах командной строки,
getopt_long
переставляет аргументы таким образом, что сначала обрабатываются все опции, а затем все операнды доступны последовательно. (Такое поведение можно запретить.)
6. Аргументы опций могут быть необязательными. Для таких опций считается, что аргумент присутствует, если он находится в одной строке с опцией. Это работает лишь для коротких опций. Например, если -х такая опция и дана строка '
foo -хYANKEES -y
',
аргументом
– х
является '
YANKEES
'. Для '
foo -х -y
' у
– х
нет аргументов.
7. Программы могут разрешить длинным опциям начинаться с одной черточки (Это типично для многих программ X Window.)
Многое из этого станет яснее, когда позже в этой главе мы рассмотрим
getopt_long
.
GNU Coding Standards уделяет значительное место перечислению всех длинных и коротких опций, используемых программами GNU. Если вы пишете программу, использующую длинные опции, посмотрите, нет ли уже использующихся имен опций, которые имело бы смысл использовать и вам.
2.2. Базовая обработка командной строки
Программа на С получает доступ к своим аргументам командной строки через параметры
argc
и
argv
. Параметр
argc
является целым, указывающим число имеющихся аргументов, включая имя команды. Есть два обычных способа определения
main
, отличающихся способом объявления
argc
:
int main(int argc, char *argv[]) int main(int argc, char **argv)
{ {
... ...
} }
Практически между двумя этими объявлениями нет разницы, хотя первое концептуально более понятно:
argc
является массивом указателей на символы. А второе определение технически более корректно, это то, что мы используем. На рис. 2.2 изображена эта ситуация.
Рис. 2.2. Память для
argc
По соглашению,
argv[0]
является именем программы. (Детали см. в разделе 9.1.4.3. «Имена программ и
argv[0]
».) Последующие элементы являются аргументами командной строки. Последним элементом массива
argv
является указатель
NULL
.
argc
указывает, сколько имеется аргументов; поскольку в С индексы отсчитываются с нуля, выражение '
argv[argc] == NULL
' всегда верно. Из-за этого, особенно в коде для Unix, вы увидите различные способы проверки окончания списка аргументов, такие, как цикл с проверкой, что счетчик превысил
argc
, или '
argv[i] == 0
', или '
*argv != NULL
' и т.д. Они все эквивалентны.
2.2.1. Программа
echo
V7
Возможно, простейшим примером обработки командной строки является программа V7
echo,
печатающая свои аргументы в стандартный вывод, разделяя их пробелами и завершая символом конца строки. Если первым аргументом является
– n
, завершающий символ новой строки опускается. (Это используется для приглашений из сценариев оболочки.) Вот код [28] :
Всего 23 строки! Здесь есть два интересных момента. Во-первых, уменьшение
argc
и одновременное увеличение
argv
(строки 12 и 13) являются обычным способом пропуска начальных аргументов. Во-вторых, проверка наличия
– n
(строка 10) является упрощением.
– no-newline-at-the-end
также работает. (Откомпилируйте и проверьте это!)
Ручной разбор опций обычен для кода V7, поскольку функция
getopt
не была еще придумана.
Наконец, здесь и в других местах по всей книге, мы видим использование ключевого слова register. Одно время это ключевое слово давало компилятору подсказку, что данная переменная должна по возможности размещаться в регистре процессора. Теперь это ключевое слово устарело; современные компиляторы все основывают размещение переменных в регистрах на анализе исходного кода, игнорируя ключевое слово
register
. Мы решили оставить использующий это слово код, как есть, но вы должны знать, что оно больше не имеет реального применения. [29]
29
Когда мы спросили Джима Мейеринга (Jim Meyering), сопроводителя Coreulils, о наличии
register
в GNU Coreutils, он дал нам интересный ответ. Он удаляет эти слова при изменении кода, но в остальных случаях оставляет их на месте, чтобы облегчить интеграцию сделанных изменений с существующими версиями — Примеч. автора.
2.3. Разбор опций:
getopt
и
getopt_long
Примерно в 1980-х группа поддержки Unix для System III в AT&T заметила, что каждая программа Unix использовала для разбора аргументов свои собственные методики. Чтобы облегчить работу пользователей и программистов, они разработали большинство из перечисленных ранее соглашений. (Хотя изложение в System III справки для intro(1) значительно менее формально, чем в стандарте POSIX.)
Группа поддержки Unix разработала также функцию
getopt
, вместе с несколькими внешними переменными, чтобы упростить написание кода, придерживающегося стандартных соглашений. Функция GNU
getopt_long
предоставляет совместимую с
getopt
версию, а также упрощает разбор длинных опций в описанной ранее форме.