Главная » Программирование для UNIX » Команда pick: пробелы и аргументы

0

Практически все,  что потребуется для написания команды pick в оболочке, уже  было описано ранее. Единственное, с чем вы еще не знакомы,  –  это  механизм чтения  пользовательского ввода. Встроенная в оболочку функция read считывает только одну строку текста с устройства стандартного ввода и присваивает полученный текст (без символа новой строки) указанной переменной:

$ read  greeting

hello, world                                  Ввести новое значение для  greeting

$ echo $greeting

hello, world

$

Функция read чаще всего используется в .profile для  настройки окру жения при входе в систему, главным образом для задания переменных оболочки, таких как TERM.

Читать данные read может только со стандартного ввода; ее даже нель зя перенаправить. Ни одна из встроенных в оболочку команд не может быть  перенаправлена  (в отличие от операторов управления типа  for) при помощи > или <:

$ read  greeting </etc/passwd

goodbye                               В любом  случае надо ввести значение

illegal io                           Оболочка сообщает об ошибке

$ echo $greeting

goodbye                               greeting имеет введенное значение, а не значение из файла

$

Можно было бы назвать такое положение вещей ошибкой в оболочке, но такова реальность. К счастью, обычно  можно решить проблему, перенаправив цикл, в котором находится read. Это будет  ключевым моментом реализации команды pick:

#  pick:    выбор  аргументов PATH=/bin:/usr/bin

for  i                            #  для каждого  аргумента do

echo –n "$i?  "  >/dev/tty

read  response

case  $response  in y*)  echo $i  ;;

q*)  break esac

done </dev/tty

Команда echo –n уничтожает заключительный  символ новой  строки, поэтому ответ может быть введен  на той же строке, где находится приглашение на ввод. И, конечно же, приглашения на ввод выводятся в

/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 $@ применялась для защиты аргументов пользовательской команды.

Подводим итоги:

•                    $* и $@  преобразуются в аргументы и  повторно просматриваются; из-за  пробелов,  имеющихся в  аргументе, он  превращается  в  несколько аргументов.

•                    "$*" представляет собой  единое  слово,  составленное из  всех  аргу ментов командного файла, соединенных вместе, с пробелами.

•                    for  i ничем не отличается от for i in "$@"; пробелы в аргументах не обрабатываются особым образом, результатом является список слов, совпадающих с исходными аргументами.

Если аргументы для команды pick не заданы, то, вероятно, она должна читать свой стандартный ввод, так что можно было написать

$ pick  <mailinglist

вместо

$ pick  `cat mailinglist`

Но не будем  исследовать эту версию pick:  в ней возникают некоторые проблемы, и она гораздо сложнее, чем  та же  самая программа, написанная на Си, которая будет представлена в следующей главе.

Первые два из предложенных ниже упражнений сложные, но они могут кое-чему научить продвинутых программистов оболочки.

Упражнение 5.24.  Попробуйте написать команду pick, которая считывала  бы аргументы с устройства стандартного ввода, не указанные в командной строке. Она должна правильно обрабатывать пробелы. Ра ботает ли ответ q? Если  нет,  попробуйте выполнить следующее упражнение. ~

Упражнение 5.25.  Несмотря на то что встроенные функции оболочки (как read и set) не могут  быть  перенаправлены, сама  оболочка может быть  временно перенаправлена.  Прочитайте раздел sh(1), в котором описывается exec, и подумайте, как read могла бы читать с /dev/tty без вызова подоболочки. (Может быть, стоит сначала прочитать главу 7.) ~

Упражнение 5.26   (гораздо более  легкое).  Используйте read  в  своем

.profile для  инициализации TERM  и всего  от нее зависящего, как, например, шагов табуляции. ~

Источник: Керниган Б., Пайк Р., UNIX. Программное окружение. – Пер. с англ. – СПб: Символ-Плюс, 2003. – 416 с., ил.

По теме:

  • Комментарии