Чтение онлайн

на главную

Жанры

UNIX — универсальная среда программирования
Шрифт:

*) y=$m; m="" ;; # plain year

esac

/usr/bin/cal $m $y # run the real one

$

В первом операторе case проверяется число аргументов

$#
и выбирается подходящее действие. Последний шаблон в этом операторе задает вариант, выбираемый по умолчанию; если число аргументов не 0 и не 1, будет выполнен последний вариант. (Поскольку шаблоны просматриваются по порядку, вариант по умолчанию должен быть последним.) При наличии двух аргументов
m
и
y
принимают значение месяца и года, и наша команда
cal
должна выполняться как исходная команда.

Первый оператор

case
включает пару нетривиальных строк, содержащих

set `date`

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

$ date

Sat Oct 1 06:05:18 EDT 1983

$ set `date`

$ echo $1

Sat

$ echo $4

06:05:20

$

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

$1
,
$2
и т.д. Поэтому
set `date`
присваивает
$1
— день недели,
$2
— название месяца и т.д. Таким образом, при отсутствии аргументов в первом
case
месяц и год устанавливаются из текущей даты. Если был задан один аргумент, он используется в качестве месяца, а год берется из текущей даты.

Команда

set
имеет также несколько флагов, из которых наиболее часто используются флаги
– v
и
– х
— для отключения эха команд при обработке их интерпретатором. Такое отключение может оказаться необходимым в процессе отладки сложных программ на языке
shell
.

Теперь осталось только перевести значение месяца, если оно представлено в строковом виде, в число. Это делается с помощью второго оператора

case
, который практически очевиден. Единственный нюанс состоит в том, что символ
|
в шаблонах оператора
case
, как и в команде
egrep
, означает альтернативу:
малый|большой
соответствует варианту "малый" или "большой". Конечно, эти варианты можно было бы задать с помощью
[jJ]an*
и т.д. Программа допускает задание месяца строчными буквами, поскольку большинство команд работает с входным потоком, где данные записаны строчными буквами (иногда первая буква — прописная), поскольку так выглядит вывод команды
date
. Правила сопоставления шаблонов приведены в табл. 5.2.

*
Задает любую строку, включая пустую
?
Задает любой одиночный символ
[ccc]
Задает любой из символов в
ccc [a-d0-3]
эквивалентно
[abcd0123]
"..."
Задает в точности
...
; кавычки защищают от специальных символов. Аналогично действует
'...'
\c
Задает
с
буквально
a|b
Только для выражений выбора; задает
а
или
b
/
Для имен файлов; соответствует только символу
/
в выражении; для выражений выбора сопоставляется, как любой другой символ
.
Если это первый символ в имени файла, то сопоставляется только с явно заданной точкой в выражении

Таблица 5.2: Правила сопоставления шаблонов в интерпретаторе

Два последних варианта второго оператора

case
относятся к случаю, когда единственный аргумент может быть годом; напомним, что в первом операторе
case
предполагалось, что аргументом является месяц. Если это число, которым может быть задан месяц, то ничего не происходит (иначе предполагается, что задан год).

Наконец, в последней строке вызывается

/usr/bin/cal
(настоящая команда
cal
) с преобразованными аргументами. Наша версия команды
cal
работает так, как этого мог бы ожидать начинающий:

$ date

Sat Oct 1 06:09:55 EDT 1983

$ cal

October 1983

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
?

Поделиться:
Популярные книги

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
7.33
рейтинг книги
Тринадцатый

Бездна

Кораблев Родион
21. Другая сторона
Фантастика:
боевая фантастика
рпг
уся
попаданцы
5.00
рейтинг книги
Бездна

Черный рынок

Вайс Александр
6. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Черный рынок

Книга тайн

Харпер Том
143. Книга-загадка, книга-бестселлер
Детективы:
прочие детективы
7.50
рейтинг книги
Книга тайн

Кодекс Охотника. Книга II

Винокуров Юрий
2. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
боевая фантастика
юмористическое фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга II

Найденыш

Шмаков Алексей Семенович
2. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Найденыш

Неучтенный элемент. Том 11

NikL
11. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 11

Барон Бранд Берс. Том 3

Limonad
3. Бранд Берс
Проза:
магический реализм
5.00
рейтинг книги
Барон Бранд Берс. Том 3

Ермак. Противостояние. Книга одиннадцатая

Валериев Игорь
11. Ермак
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Ермак. Противостояние. Книга одиннадцатая

На границе империй. Том 10. Часть 10

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 10

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Жена по ошибке

Ардова Алиса
Любовные романы:
любовно-фантастические романы
7.71
рейтинг книги
Жена по ошибке

Наномашины, внучок! Том 2

Новиков Николай Васильевич
2. Чего смотришь? Иди книгу читай
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наномашины, внучок! Том 2

Лекарь Империи 3

Карелин Сергей Витальевич
3. Лекарь Империи
Фантастика:
городское фэнтези
аниме
дорама
фэнтези
попаданцы
5.00
рейтинг книги
Лекарь Империи 3