Читаем UNIX полностью

Аргумент обрабатывается интерпретатором, поэтому \$ становится $, а $1 заменяется на значение n. Мы предпочитаем решение с апострофами (одиночными кавычками), поскольку при использовании кавычек в типичной программе awk появится слишком много символов \.

Другим примером может служить программа 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

$

Перейти на страницу:

Похожие книги

Все жанры