- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
UNIX — универсальная среда программирования - Брайан Керниган
Шрифт:
Интервал:
Закладка:
Другим примером может служить программа addup n, суммирующая значения n-го поля:
awk '{s += $'$1'}
END {print s}'
В третьем примере вычисляются отдельные суммы значений каждого n-го поля и полная сумма:
awk '
BEGIN { n = '$1' }
{ for (i=1; i <= n; i++)
sum[i] += $1
}
END { for(i = 1; i <= n; i++)
{
printf "%6g ", sum[i]
total += sum[i]
}
printf "; total = %6g ", total
}'
Нам удобнее было использовать часть BEGIN для засылки значения в переменную n, чем засорять конец программы кавычками.
Основная трудность во всех приведенных выше примерах состоит не в том, чтобы следить за кавычками (хотя и это хлопотно), а в том, что программы, составленные показанным способом, могут читать только свой стандартный входной поток. Нет никакой возможности передать им сразу и параметр n, и произвольно длинный список имен файлов. Для этого требуется определенная техника программирования на языке shell; которую мы рассмотрим в следующей главе.
Служебная программа-календарь на языке awkВ нашем последнем примере демонстрируются ассоциативные массивы, а также иллюстрируется взаимодействие с интерпретатором и частично показывается процесс разработки программы.
Задача состоит в создании системы, посылающей вам каждое утро почту с напоминанием об ожидаемых событиях. (Возможно, такая календарная система уже есть; см. руководство по calendar(1).) В этом разделе применяется иной подход. Вам будут перечислены события, происходящие сегодня и, кроме того, предстоящие сегодняшние и завтрашние события. Правильный учет праздников и выходных оставлен вам в качестве упражнения.
Прежде всего нужно предусмотреть место, где будет храниться календарь. Имеет смысл разместить его в файле с именем calendar в каталоге /usr/you:
$ cat calendar
Sep 30 день рождения мамы
Oct 1 обед с Джо, полдень
Oct 1 встреча в 16:00
$
Далее, необходимо уметь просматривать календарь, отыскивая определенную дату. Существует масса вариантов; мы остановимся на языке awk, поскольку с его помощью легче выполнять арифметические операции по переходу от одной даты к другой, однако для этой цели подходят и другие программы, например sed и egrep. Конечно, строки, выбранные из файла calendar, посылаются командой mail.
Наконец, вам придется научиться автоматически и безотказно просматривать календарь каждый день, скажем, рано утром. Это можно сделать с помощью команды at, о которой упоминалось в гл. 1.
Если ограничить календарь таким форматом, в котором каждая строка начинается с названия месяца и числа (как это делает команда date), то составить первый вариант программы календаря нетрудно:
$ date
Thu Sep 29 15:23:12 EDT 1983
$ cat bin/calendar
# calendar: version 1 - today only
awk <$HOME/calendar '
BEGIN { split ("'"`date`"'", date) }
$1 == date[2] && $2 == date[3]
' | mail $NAME
$
Функция в части BEGIN разбивает дату, выдаваемую командой date, и заносит ее в массив; второй и третий элементы массива — месяц и число. Мы предполагаем, что в переменной интерпретатора NAME находится имя, под которым вы вошли в систему. Вы заметили, какая нужна сложная последовательность кавычек, чтобы "поймать" результат действия команды date в середине строки программы awk. Более простым решением является передача даты в первой строке входного потока:
$ cat /bin/calendar
# calendar: version 2 - today only, no quotes
(date; cat $HOME/calendar) |
awk '
NR == 1 { mon = $2; day = $3 } # set the date
NR > 1 && $1 == mon && $2 == day # print calendar lines
' | mail $NAME
$
На следующем шаге требуется так изменить программу, чтобы искать сообщение с завтрашней датой так же, как и с сегодняшней. Наибольшие усилия затрачиваются на прибавление единицы к сегодняшнему числу. Но в конце месяца нужно перейти к следующему месяцу, а число приравнять единице. Конечно, число дней в разных месяцах различно. Именно здесь на помощь приходит ассоциативный массив. Два массива days и nextmon, индексами которых служат названия месяцев, содержат число дней месяца и название следующего месяца. Например, days["Jan"] равно 31, a nextmon["Jan"] есть Feb. Вместо того чтобы написать множество операторов типа
days["Jan"] = 31; nextmon["Jan"] = "Feb"
days["Feb"] = 28; nextmon["Feb"] = "Mar"
...
мы воспользуемся функцией split для преобразования удобно записываемой структуры данных в то, что требуется:
$ cat calendar
# calendar: version 3 -- today and tomorrow
awk <$HOME/calendar '
BEGIN {
x = "Jan 31 Feb 28 Mar 31 Apr 30 May 31 Jun 30 "
"Jul 31 Aug 31 Sep 30 Oct 31 Nov 30 Dec 31 Jan 31"
split(x, data)
for (i = 1; i < 24; i += 2) {
days[data[i]] = data[i+1]
nextmon[data[i]] = data[i+2]
}
split("'"`date`", date)
mon1 = date[2]; day1 = date[3]
mon2 = mon1; day2 = day1 + 1
if (day1 >= days[mon1]) {
day2 = 1
mon2 = nextmon[mon1]
}
}
$1 == mon1 && $2 == day1 || $1 == mon2 && $2 == day2
' | mail $NAME
$
Обратите внимание на то, что Jan появляется дважды в структуре данных; такое "сторожевое" значение упрощает обработку для декабря.
На последнем шаге нужно обеспечить запуск программы календаря на каждый день. Можно делать это и самому, не забывая задавать команду (каждый день!)
$ at 5 am
calendar
ctl-d
$
Однако такое решение нельзя считать автоматическим или надежным. Хитрость заключается в том, чтобы не только запустить программу calendar, но и обеспечить следующий ее запуск.
$ cat early.morning
calendar
echo early morning | at 5am
$
Вторая строка файла early.morning готовит еще одну команду at для следующего дня, поэтому, раз начавшись, эта последовательность команд сама себя воспроизводит. В команде at устанавливается PATH, текущий каталог и другие параметры запускаемых ею команд, так что больше ничего и не требуется.
Упражнение 4.11Измените программу calendar так, чтобы она учитывала выходные дни: для пятницы "завтра" должно означать субботу, воскресенье или понедельник. Далее измените ее так, чтобы можно было учесть високосные годы. Следует ли учитывать праздники? Как бы вы это сделали?
Упражнение 4.12Должна ли программа календарь учитывать даты, находящиеся в середине строки, а не только в ее начале? Как быть с датой, заданной в другом формате, например 10/1/83?
Упражнение 4.13Почему в программе calendar используется $NAME, а не обращение к getname?
Упражнение 4.14Напишите вашу версию команды rm, которая не удаляет файлы, а пересылает их во временный каталог, используя команду at для очистки каталога в то время, пока вы не работаете.
Дополнительная информацияЯзык awk довольно громоздкий, и в рамках одной главы трудно показать все его возможности. Поэтому мы перечислим здесь еще ряд моментов, на которые необходимо обратить внимание в справочном руководстве:
• Переключение выходного потока оператора print в файлы и программные каналы: за каждым оператором print или printf может следовать символ > и имя файла (в виде строки в кавычках или переменной); выходной поток будет направлен в этот файл. Как и для интерпретатора, >> означает добавление, а не запись. Для вывода в программный канал используется символ |, а не >.
• Запись в несколько строк: если разделитель записей RS установлен равным концу строки, то входные записи разделяются пустой строкой. В таком случае несколько входных строк могут рассматриваться как одна запись.
• "Шаблон, шаблон" в качестве селектора: как и в случае команд sed и ed, с помощью пары шаблонов можно указать диапазон строк. Так выбираются строки, начиная с соответствующей первому шаблону, до строки, соответствующей второму шаблону. Приведем простой пример:
NR == 10, NR == 20
Здесь задаются строки от 10-й по 20-ю включительно.
4.5 Хорошие файлы и хорошие фильтры
Несмотря на то что в качестве примеров использования языка awk приводились независимые программы, в большинстве случаев его применяют для написания простых программ в одну или две строки, являющихся фильтрами в больших конвейерах. Это справедливо для большинства фильтров: редко поставленная задача может быть решена с помощью одного фильтра, чаще она разбивается на подзадачи, где фигурируют несколько фильтров, объединенных в конвейер. Такую реализацию программных компонентов называют основным принципом организации программного мира UNIX. Фильтры буквально "пронизывают" всю систему, и очень важно понимать причины этого.

