Книга: UNIX — универсальная среда программирования
3.4 Аргументы и параметры команд
3.4 Аргументы и параметры команд
Хотя команда nu
, как она задумывалась, удовлетворяет своему назначению, многие программы на языке shell
могут обрабатывать аргументы, так что при их запуске можно задавать имена файлов и флаги.
Допустим, вы хотите создать программу с именем cx
для установки права доступа к файлу на выполнение, так что
$ cx nu
есть сокращенная запись для
$ chmod +x nu
Вы уже знаете почти все, чтобы это сделать. Вам нужен файл cx
, содержимое которого суть
chmod +x filename
Единственное, что требуется выяснить — как сообщить команде cx
имя файла, так как при каждом запуске cx
оно будет иным.
Если интерпретатор выполняет командный файл, то каждое вхождение $1
заменяется первым аргументом, каждое вхождение $2
— вторым и т.д. до $9
. Поэтому если файл cx
содержит строку
chmod +x $1
то при выполнении команды
$ cx nu
порожденный интерпретатор заменит "$1
" на первый аргумент "nu
". Рассмотрим всю последовательность операций:
$ echo 'chmod +x $1' >cx
Вначале создадим cx
$ sh cx сх
Сделать сам файл cx выполняемым
$ echo echo Hi, there! >hello
Приготовим тест
$ hello
Попробуем
hello: cannot execute
Сделаем файл выполняемым
$ cx hello
$ hello
Попробуем снова
Hi, there!
Работает
$ mv cx /usr/you/bin
Установим команду cx
$ rm hello
Уберем ненужное
$
Заметьте, что мы задали
$ sh cx сх
в точности так, как сделал бы автоматически интерпретатор, если бы cx
была выполняемой и можно было бы задать
$ cx сх
А как быть, если нужно работать с несколькими аргументами, например, заставить программу cx
воздействовать сразу на несколько файлов? Прямолинейное решение состоит в том, чтобы включить девять аргументов в командный файл:
chmod +x $1 $2 $3 $4 $5 $6 $7 $8 $9
(Это годится только для девяти аргументов, так как конструкция $10
распознается как "первый аргумент, за которым следует 0"!) Если пользователь такого командного файла задаст меньше девяти аргументов, то недостающие окажутся пустыми строками. Это приведет к тому, что только настоящие аргументы будут переданы chmod
порожденным интерпретатором. Такое решение, конечно, приемлемо, но не вполне корректно и не подходит для случая с числом аргументов более девяти.
С учетом упомянутой выше трудности интерпретатор предоставляет сокращенную запись $*
, означающую "все аргументы". В этом случае правильно определить cx
:
chmod +x $*
что является эффективным при любом числе аргументов.
Используя $*
в своем репертуаре, вы можете создать некоторые полезные командные файлы, такие, как lc
или m
:
$ cd /usr/you/bin
$ cat lc
#lc: подсчет числа строк в файлах
wc -l $*
$ cat m
#m: точный способ послать почту
mail $*
$
Обе команды можно осмысленно использовать и без аргументов. Если нет аргументов, $*
будет пустым, и wc
и mail
вообще не получат никаких аргументов. С аргументами или без них команда вызывается правильно:
$ lc /usr/you/bin/*
1 /usr/you/bin/cx
2 /usr/you/bin/lc
2 /usr/you/bin/m
1 /usr/you/bin/nu
2 /usr/you/bin/what
1 /usr/you/bin/where
9 total
$ ls /usr/you/bin | lc
6
$
Эти и другие команды, описываемые в настоящей главе, являются командами пользователя, т.е. вы создаете их для себя и помещаете в свой каталог /bin
, поэтому вряд ли они должны стать общедоступными. В гл. 5 мы исследуем вопрос создания общедоступных программ на языке shell
.
Аргументами командного файла не обязательно должны быть имена файлов. Рассмотрим в качестве примера поиск в каталоге, где хранится личный телефонный справочник. Если у вас есть файл с именем /usr/you/lib/phone-book
, содержащий строки следующего вида:
dial-a-joke 212-976-3838
dial-a-prayer 212-246-4200
dial santa 212-976-3636
dow jones report 212-976-4141
то для поиска в нем можно воспользоваться командой grep
. (Ваш собственный каталог lib
— хорошее хранилище таких частных баз данных.) Поскольку команда grep
не определяет формат информации, можно искать имена, адреса, индексы или еще какие-нибудь нужные вам сведения. Составим справочную программу для каталога, которой дадим имя 411
по номеру одной из телефонных справочных служб:
$ echo 'grep $* /usr/you/lib/phone-book' > 411
Что-то не так
$ cx 411
$ 411 joke
dial-a-joke 212-976-3838
$ 411 dial
dial-a-joke 212-976-3838
dial-a-prayer 212-246-4200
dial santa 212-976-3636
$ 411 'dow jones'
grep: can't open jones
$
Последний пример вскрывает потенциальную проблему: хотя dow jones
представляет для команды 411
единый аргумент, он содержит пробел и уже не заключен в апострофы, поэтому порожденный интерпретатор, выполняющий команду 411
, преобразует его в два аргумента для grep
, как если бы вы задали
$ grep dow jones /usr/you/lib/phone-book
что, очевидно, неверно.
Один из возможных путей обойти эту проблему основан на том, как интерпретатор трактует кавычки. Хотя все, что заключено в '...'
, не затрагивается, интерпретатор "заглядывает" внутрь "..."
в поиске комбинаций с $
, , `...`
. Поэтому если изменить команду 411 следующим образом:
$ grep "$*" /usr/you/lib/phone-book
то $*
заменяется на аргументы, но команде grep
передается как один аргумент, даже при наличии пробелов:
$ 411 dow jones
dow jones report 212-976-4141
$
Кстати, можно сделать с помощью флага -y
команду grep
(а значит, и 411
) независимой от использования строчных или прописных букв:
$ grep -y pattern ...
При наличии флага -y
строчные буквы из шаблона могут сопоставляться с прописными буквами из входного потока. (Такой флаг есть в седьмой версии, но отсутствует в других системах.)
Более подробно аргументы команд мы рассмотрим в гл. 5, но одно важное замечание необходимо сделать здесь. Аргумент $0
— это имя выполняемой программы; в случае cx $0
есть "cx"
. Новое применение $0
находит в реализации программ 2
, 3
, 4
, …, которые печатают свой выходной поток в несколько столбцов:
$ who | 2
drh tty0 Sep 28 21:23 cvw tty5 Sep 28 21:09
dmr tty6 Sep 28 21:10 scj tty7 Sep 28 22:11
you tty9 Sep 28 23:00 jib ttyb Sep 28 19:58
$
Реализация команд 2
, 3
, … идентична. По существу, они являются связями с одним файлом:
$ ln 2 3; ln 2 4; ln 2 5; ln 2 6
$ ls -l [1-9]
167222 -rwxrwxrwx 5 you 51 Sep 28 23:21 2
167222 -rwxrwxrwx 5 you 51 Sep 28 23:21 3
167222 -rwxrwxrwx 5 you 51 Sep 28 23:21 4
167222 -rwxrwxrwx 5 you 51 Sep 28 23:21 5
167222 -rwxrwxrwx 5 you 51 Sep 28 23:21 6
$ ls /usr/you/bin | 5
2 3 4 411 5
6 cx lc m nu
what where
$ cat 5
# 2, 3, ...: печать в n столбцов
pr -$0 -t -11 $*
$
Флаг -t
убирает заголовки в начале страницы, а флаг -ln
устанавливает размер страницы равным n строк. Имя программы становится числом столбцов, т.е. аргументов для команды pr, так что выходной поток печатается строками по несколько столбцов, число которых определено аргументом $0
.
- 3.1 Структура командной строки
- 3.2 Метасимволы
- 3.3 Создание новых команд
- 3.4 Аргументы и параметры команд
- 3.5 Результат выполнения программы в качестве аргумента
- 3.6 Переменные языка shell
- 3.7 Еще раз о переключении ввода-вывода
- 3.8 Циклы в shell-программах
- 3.9 Программа bundle: соберем все воедино
- 3.10 Для чего нужно программировать на языке shell!
- Аргументы программы
- Пример 4-5. Позиционные параметры
- Пример 4-7. Использование команды shift
- 8.3. Аргументы и параметры функций
- Инструмент командной строки gbak
- Основные параметры ЭЛТ-мониторов
- Инструмент командной строки gfix
- 5.4 Команда trap: обработка прерываний
- Аргументы функции в Python
- Параметры конфигурационного файла InterBase
- Параметры в ibconfig