Изменяя значение поля, следует помнить о том, что содержимое входного файла на самом деле не меняется. Изменению подвергается только копия файла, которая хранится в буфере 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 |