Литмир - Электронная Библиотека
ЛитМир: бестселлеры месяца
Содержание  
A
A

4.4 Язык

awk
поиска и обработки шаблонов

Некоторые ограничения

sed
преодолены в программе
awk
. Принцип работы этой программы сходен с принципом работы программы
sed
, но синтаксически она ближе к языку программирования Си, чем к текстовому редактору. Способ задания команды такой же, как и для
sed
:

$ awk 'программа' имена_файлов...

но программа другая:

шаблон {действие}

шаблон {действие}

...

Программа

awk
читает входной поток по одной строке из указанных файлов. Строки сопоставляются с шаблонами по порядку; для каждого шаблона, соответствующего строке, выполняется необходимое действие. Как и в редакторе
sed
, входные файлы здесь не изменяются.

Шаблоны могут быть регулярными выражениями в

sed
или более сложными условиями, напоминающими язык Си. Приведем простой пример (такого же результата можно добиться с помощью команды
egrep
):

$ awk '/регулярное_выражение/ {print}' имена_файлов...

Печатается каждая строка, соответствующая регулярному выражению.

Шаблоны или действия могут отсутствовать. Если отсутствует действие, то по умолчанию печатаются строки, соответствующие шаблону, поэтому команда

$ awk '/регулярное_выражение/' имена_файлов...

эквивалентна предыдущей. Наоборот, если отсутствует шаблон, то действие выполняется для каждой входной строки. Следовательно, команда

$ awk '{print}' имена_файлов...

дает те же результаты, что и команда

cat
, хотя действует медленнее.

Теперь перейдем к более интересным примерам, но прежде сделаем одно замечание. Как и в случае

sed
, программу команды
awk
можно получать из файла:

$ awk -f кмд файл имена_файлов...

Поля. В программе

awk
каждая входная строка автоматически разбивается на поля, т.е. последовательности символов без пробелов, разделенные пробелами и символами табуляции. По этому определению выходной поток команды
who
имеет пять полей:

$ who

you tty2 sep 29 11:53

jim tty4 sep 29 11:27

$

Поля обозначаются как

$1
,
$2
, …,
$NF
, где
NF
— переменная, значение которой установлено равным числу полей. В нашем случае
NF=5
для обеих строк. (Учтите разницу между
NF
, числом полей и
$NF
— последним полем строки. В отличие от интерпретатора в программе
awk
только номера полей начинаются с
$
; переменные не имеют такого префикса.) Например, следующая команда выдаст поле "размер файла" из результата выполнения команды
du -а

$ du -a | awk '{print $2}'

а для печати имен пользователей, работающих в системе, и времени входа нужно задать:

$ who awk '{print $1, $5}'

you 11:53

jim 11:27 $

Для печати имени и времени входа в систему, упорядоченных по времени, зададим:

$ who awk '{print $5, $1}' | sort

11:27 jim

11:53 you

$

Это альтернативные решения примеров, приведенных выше в данной главе, в которых использовалась команда

sed
. Хотя с программой
awk
проще работать в подобных случаях, она обычно выполняется медленнее как в начальной фазе, так и при большом входном потоке.

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

-F
(здесь прописная буква). Например, поля в файле паролей
/etc/passwd
разделяются двоеточиями:

$ sed 3q /etc/passwd

root:3D.fHR5KoB.3s:0:1:S.User:/:

ken:y.68wdl.ijayz:6:1:K.Thompson:/usr/ken:

dmr:z4u3dJWbg7wCk:7:1:D.M.Ritchie:/usr/dmr:

$

Для печати имен пользователей, образующих первое поле, можно задать:

$ sed 3q /etc/passwd | awk -F : '{print $1}'

root

ken

dmr

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

Печать

В программе

awk
, помимо числа входных полей, доступна и другая интересная информация. Встроенная переменная
NR
хранит номер текущей входной "записи", т.е. строки. Поэтому для вставки номера строки перед строкой входного потока достаточно задать:

$ awk '{print NR, $0}'

Поле

$0
обозначает всю входную строку без изменений. В операторе
print
фрагменты, отделяемые запятой, печатаются через символы разделения полей выходного потока, которые по умолчанию служат пробелами.

Формат печати оператора

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

$ awk '{printf "%4d %s\n", NR, $0}'

Выражение

%4
задает десятичное целое число (
NR
) в поле размером в четыре цифры,
%S
— строка символов (
$0
),
\n
— символ перевода строки, который нужен потому, что оператор
printf
не выдает автоматически пробелы или символы перевода строк. Оператор
printf
сходен с аналогичной Си функцией (см. справочное руководство по
printf(3)
).

50
{"b":"248117","o":1}
ЛитМир: бестселлеры месяца