Книга: UNIX — универсальная среда программирования
5.7 Команда pick: пробелы или аргументы
Разделы на этой странице:
5.7 Команда pick
: пробелы или аргументы
Вы уже достаточно подготовлены для того, чтобы написать команду pick
на языке shell
. Единственным новым средством является механизм чтения входного потока пользователя. Встроенная команда интерпретатора read
читает одну строку текста из стандартного входного потока и присваивает ее (без перевода строки) в качестве значения указанной переменной:
$ read greeting
Вводим новое значение для приветствия
hello, world
$ echo $greeting
hello, world
$
Самым типичным примером использования команды read
в файле .profile
служит установка значений переменных среды при входе в систему, прежде всего установка переменных интерпретатора типа TERM
.
Команда read
может читать только из стандартного входного потока; его нельзя даже переключить. Ни одну из встроенных команд интерпретатора (в отличие от основных структур управления типа for
) нельзя переключить с помощью операций >
или <
:
$ read greeting </etc/passwd
Тем не менее надо ввести значение
goodbye
illegal io
Сейчас shell сообщает об ошибке
$ echo $greeting
greeting получает введенное значение,
goodbye
а не значение из файла
$
Это можно считать ошибкой интерпретатора, но такова жизнь. К счастью, можно предусмотреть переключение в цикле, охватывающем команду read
, что является основным принципом реализации команды pick
:
# pick: select arguments
PATH=/bin:/usr/bin
for i # for each argument
do
echo -n "$i? " >/dev/tty
read response
case $response in
y*) echo $i ;;
q*) break
esac
done </dev/tty
Обращение echo -n
подавляет заключительный символ перевода строки, так что переменную response
можно вывести на той же строке, что и приглашение. Конечно, приглашения выдаются на устройство /dev/tty
, поскольку стандартный выходной поток, по всей вероятности, не выводится на терминал.
Оператор break
заимствован из языка Си: он завершает выполнение самого внутреннего цикла, в нашем случае for
, когда вводится q
. Мы выбрали символ q
как сигнал прекращения процесса выбора потому, что это легко сделать, потенциально удобно и не противоречит другим программам.
Интересно поэкспериментировать с пробелами в аргументах для команды pick
:
$ pick '1 2' 3
1 2?
3?
$
Если вы хотите узнать, как команда pick
читает свои аргументы, запустите ее и нажмите клавишу RETURN после каждого приглашения. В том виде, в каком написана эта команда, она выполняется отлично: в цикле for i
аргументы обрабатываются правильно. Мы могли бы написать цикл другими способами:
$ grep for pick
Выясните, что делает эта версия
for i in $*
$ pick '1 2' 3
1?
2?
3?
$
Эта версия не работаете поскольку операнды в цикле снова распознаются, а наличие пробелов в первом аргументе приводит к тому, что он разбивается на два аргумента. Попробуйте взять в кавычки $*
:
$ grep for pick
Попробуем другую версию
for i in "$*"
$ pick '1 2' 3
1 2 3?
$
Такая версия тоже не работает, поскольку "$*
" является единым словом, которое образовано из всех аргументов, объединенных вместе с разделяющими пробелами. Но решение все-таки есть (это почти черная магия): строка трактуется особым образом интерпретатором и преобразуется в нужное число аргументов для командного файла:
$ grep for pick
Попробуем третью версию
for i in "$@" '
$ pick '1 2' 3
1 2?
3?
$
Строка $@
, не взятая в кавычки, идентична $*
; она обрабатывается иначе, только если заключена в кавычки. Мы использовали ее в команде overwrite
, чтобы сохранить аргументы для команды пользователя.
В итоге мы можем сформулировать следующие правила: $*
и $@
раскрываются как аргументы и снова распознаются; наличие пробелов в аргументах приводит к разбиению их на несколько аргументов;
• "$*
" является единым словом, которое образовано из всех аргументов командного файла, объединенных вместе с пробелами;
• «$*
» идентично аргументам, получаемым командным файлом: пробелы в аргументах игнорируются, в результате получается список слов, идентичных исходным аргументам.
Если команда pick
не имеет аргументов, она, по-видимому, должна читать стандартный входной поток, поэтому можно задать
$ pick < mailinglist
вместо
$ pick `cat mailinglist`
Но мы не будем исследовать эту версию команды pick
во избежание некоторых неприятных осложнений. Кроме того, значительно проще написать такую же программу на Си. С ней вы познакомитесь в следующей главе.
Первые два из приведенных ниже упражнений достаточно сложны, но полезны даже для опытных программистов, работающих на языке shell
.
Упражнение 5.24
Попробуйте написать программу pick
, которая читает аргументы из стандартного входного потока, если ничего не задано в командной строке. Она должна правильно обрабатывать пробелы. Будет ли допустим ответ q
? Если нет, то попытайтесь выполнить следующее упражнение.
Упражнение 5.25
Хотя встроенные команды интерпретатора, такие, как read
и set
, нельзя переключить, можно временно переключить сам интерпретатор. Прочтите в справочном руководстве раздел по sh(1)
, в котором описывается команда exec
, и придумайте, как читать из /dev/tty
без вызова порожденного интерпретатора. (Может оказаться полезным сначала прочитать гл. 7.)
Упражнение 5.26
(Более простое.) Используйте команду read
в вашем файле .profile
для инициации TERM
, а также всего, что зависит от нее, например позиции табуляции.
- 5.1 Совершенствование команды cal
- 5.2 Что представляет собой команда which?
- 5.3 Циклы while и until: контроль входа в систему
- 5.4 Команда trap: обработка прерываний
- 5.5 Команда overwrite: замена файла
- 5.6 Команда zap: уничтожение процесса по имени
- 5.7 Команда pick: пробелы или аргументы
- 5.8 Команда news: служба информации пользователей
- 5.9 Команды get и put: контроль изменении файла
- 5.10 Заключение
- 5.4 Команда trap: обработка прерываний
- Аргументы функции в Python
- Scrum-команда: состав
- Фактические аргументы
- Команда make и make-файлы
- 21.3.1. Команда arch — вывод архитектуры компьютера
- Глава 4 Контент + команда = SMM
- Команда break в Python:
- Необязательные аргументы
- Начните закрывать пробелы
- Близость между командами разработчиков и эксплуатации в компании Sparkle Corp
- Рабочая группа, она же руководящая команда