Литмир - Электронная Библиотека
Содержание  
A
A

  S  М Tu  W Th  F  S

                    1

  2  3  4  5  6  7  8

  9 10 11 12 13 14 15

 16 17 18 19 20 21 22

 23 24 25 26 27 28 29

 30 31

$ cal dec

December 1983

  S  M Tu  W Th  F  S

              1  2  3

  4  5  6  7  8  9 10

 11 12 13 14 15 16 17

 18 19 20 21 22 23 24

 25 26 27 28 29 30 31

$

При обращении к

cal 1984
будет напечатан календарь на весь 1984 год. Наша обобщенная команда
cal
выполняет то же задание, что и исходная, но более простым и легко запоминающимся способом. Поэтому мы предпочитаем называть ее
cal
, а не
calendar
(что уже является командой), или как-нибудь еще с менее простой мнемоникой, например
ncal
. При использовании одного и того же имени пользователю не придется вырабатывать новые рефлексы для печати календаря.

Прежде чем завершить обсуждение оператора

case
, следует объяснить, почему правила сопоставления шаблонов в интерпретаторе отличаются от правил для редактора
ed
и его производных. Действительно, наличие двух видов шаблонов означает, что нужно изучать два набора правил и иметь два программных фрагмента для их обработки. Некоторые различия вызваны просто неудачным выбором, который никогда не был зафиксирован. В частности, нет никаких причин (кроме того, что так сложилось исторически), по которым
ed
использует
'.'
а интерпретатор —
'?'
для задания единственного символа. Но иногда шаблоны применяются по-разному. Регулярные выражения в редакторе используются для поиска последовательности символов, которая может встретиться в любом месте строки; специальные символы и $ нужны, чтобы направить поиск с начала или конца строки. Но для имен файлов мы хотим, чтобы направление поиска определялось по умолчанию, поскольку это наиболее общий случай. Было бы неудобным задавать нечто вроде

$ ls ^?*.с$
Так не получится

вместо

$ ls *.с

Упражнение 5.1

Если пользователи предпочтут вашу версию команды

cal
, как бы вы сделали ее общедоступной? Что следует предпринять, чтобы поместить ее в
/usr/bin
?

Упражнение 5.2

Имеет ли смысл сделать так, чтобы при обращении

cal 83
был напечатан календарь за 1983 г.? Как в этом случае задать вывод календаря?

Упражнение 5.3

Модифицируйте команду

cal
так, чтобы можно было задавать больше одного месяца, например:

$ cal oct nov

и даже диапазон месяцев:

$ cal oct-dec

Если сейчас декабрь, а вы выполняете обращение

cal jan
, то какой должен быть напечатан календарь: на январь этого года или следующего? Когда следует прекратить расширять возможности команды
cal
?

5.2 Что представляет собой команда

which
?

При обзаведении собственными версиями команд, аналогичных

cal
, возникает ряд трудностей. В частности, когда вы работаете как пользователь Мэри и вошли в систему под именем
mary
, то, вводя команду
cal
, получаете стандартную версию команды вместо новой, если, конечно, не установили в своем каталоге
bin
связь с новой командой
cal
. Это может привести к путанице: вспомните, что сообщения об ошибках в исходной, команде
cal
не очень вразумительны. Мы привели всего лишь один пример возникающих трудностей. Поскольку интерпретатор осуществляет поиск команд среди каталогов, задаваемых переменной
PATH
, всегда есть вероятность столкнуться не с той версией команды, которую вы ожидали. Например, если вы задали команду, скажем
echo
, имя выполняемого на самом деле файла будет
./echo
,
/bin/echo
,
/usr/bin/echo
или какое-то другое в зависимости от компонентов вашей переменной
PATH
и от того, где находятся файлы. Может случиться, что в вашей последовательности поиска ранее, чем вы ожидали, окажется выполняемый файл с правильным именем, но не с теми результатами. Наиболее типичным примером в такой ситуации является команда
test
, которую мы обсудим позднее. Ее название настолько распространено для временной версии программы, что вызовы "не тех" команд
test
происходят раздражающе часто[12]. Здесь весьма полезным средством явилась бы команда, которая помогла бы выяснить, какая версия программы должна выполняться.

Один из вариантов решения — цикл поиска по каталогам, указанным в

PATH
, выполняемого файла с данным именем. В гл. 3 мы использовали цикл
for
по именам файлов и аргументам. Здесь же нужен такой цикл:

for i in компонента в PATH

do

 если заданное имя в каталоге i

  печать полного путевого имени

done

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

sed
по значению
PATH
, заменив двоеточия на пробелы. Мы можем проверить это с помощью нашего старого друга
echo
:

$ echo $PATH

:/usr/you/bin:/bin:/usr/bin
4 компонента

$ echo $PATH | sed 's/:/ /a'

/usr/you/bin /bin /usr/bin 
Только три выдано!

$ echo `echo $PATH | sed 's/:/ /g'`

/usr/you/bin /bin /usr/bin 
По-прежнему только три

$

Однако такое решение проблематично. Пустая строка в

PATH
служит синонимом
'.'
. Поэтому перевод двоеточий в пробелы не слишком удачен — теряется информация о пустых компонентах. Для создания правильного списка каталогов пустую компоненту
PATH
нужно перевести в точку. Пустая компонента может быть в середине, начале или конце строки, так что вам придется потрудиться, чтобы учесть все возможные случаи:

вернуться

12

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

test
.

60
{"b":"248117","o":1}