Выбрать главу

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

В следующем примере на экран выводятся имена учеников и их рейтинговые очки, а рейтинг ученика по имени M. Tansley уменьшается на единицу:

$ awk '{if($1="M. Tansley") $6=$6-1; print $1, $6}' grade.txt

M.Tansley 39

J.Lulu 24

P.Bunny 35

J.Troll 26

L.Tansley 30

Изменение значения текстового поля

Для изменения значения текстового поля достаточно применить к нему оператор присваивания. Следующая команда при выводе на экран добавляет к имени ученика J. Troll дополнительный инициал:

$ awk '{if($1="J. Troll") $1="J. L.Troll"; print $1}' grade.txt

M.Tansley

J.Lulu

P.Bunny

J.L.Troll

L.Tansley

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

Отображение только измененных записей

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

$ awk '{if($1=="J. Troll") {$1="J. L.Troll"; print $1)}' grade.txt

J.L.Troll

Создание нового поля

Аналогично локальным переменным в сценарии awk можно создавать новые поля. Например, мы можем создать поле $8, содержащее разницу полей $6 и $7 в том случае, если значение в поле $7 больше, чем в поле $6:

$ awk 'BEGIN {print "Name\t\tDifference"} {if($6 < $7) \ {$8=$7-$6; print $1" \t"$8}}' grade.txt

Name Difference

L.Tansley 4

J.Lulu 2

Суммирование столбцов

Для вычисления суммарного рейтинга учеников секции мы создадим переменную tot и с помощью выражения tot+=$6 будем прибавлять к ней значение поля $6 при обработке каждой записи. По завершении обработки записей в процедурной части шаблона end итоговое значение переменной tot будет выведено на экран.

$ awk 'tot+=$6; END {print "Club student total points: " tot}' grade.txt

M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28

Club student total points: 155

Вероятно, вы заметили, что утилите awk не было дано указание выводить на экран все записи -oна сделала это сама. Причина такого поведения заключается в том, что выражение tot+=$6 относится к шаблонной части инструкции и не задает критерия отбора строк, т.е. применяется ко всем записям. А поскольку процедурная часть этого шаблона отсутствует, выполняется действие по умолчанию — команда print SO.

Если файл велик, можно не выводить на экран все записи, а лишь отобразить итог. Для этого достаточно взять выражение tot+=$6 в фигурные скобки, чтобы перенести его в процедурную часть инструкции:

$ awk '{tot+=$6}; END {print "Club student total points: " tot}' grade.txt

Club student total points: 155

Суммирование размеров файлов

При просмотре содержимого каталога часто требуется узнать общий размер всех файлов в нем, исключая файлы в подкаталогах и скрытые файлы. Алгоритм решения этой задачи таков: результаты работы команды ls -l (формирует список файлов с расширенной информацией о них; см. главу 1) направляются утилите awk, которая удаляет записи, начинающиеся с символа 'd' (признак каталога), и вычисляет сумму по 5–му столбцу (содержит размер файла).

Представленная ниже команда отображает список файлов текущего каталога (имя файла берется из 9–го столбца), указывая размер каждого из них, а в конце выводит суммарный размер файлов, накопленный в переменной tot:

$ ls -l | awk '/^[^d]/ {print $9"\t"$5; tot+=$5} END {print "total KB: "tot}' dev_pkg.fail 345 failedlogin 12416

messages 4260
зи1од 12810
utap 1856
wtap 7104
total KB: 38791