Язык обработки шаблонов AWK
Название AWK произошло из инициалов его разработчиков: Alfred V. Aho, Peter J. Weinberger и Brian W. Kernighan.
AWK рассматривает входной поток как список записей. Каждая запись делится на поля. На основе этой информации выполняется некоторый определённый программистом алгоритм обработки. По умолчанию разделителем записей является символ новой строки. Разделителем полей — символ пробела или табуляции, или последовательность таких символов. Символы-разделители можно явно определить в программе. Символ-разделитель полей можно определить и в командной строке.
Структура awk-программы
Программа состоит из операторов, имеющих вид:
- шаблон {действие}
или
- шаблон — когда выводятся строки с данным шаблоном.
или
- {действие} — когда действие выполняется для всех строк.
Действие состоит из последовательности операторов, разделённых точкой с запятой (;), символом перевода строки или закрывающейся скобкой.
Для дальнейших примеров будем использовать файл следующего содержания:
$ cat awk_test
Иванов К.И. 1980 50
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
Примеры
Выводим весь текст
$ awk '{print}' awk_test
Иванов К.И. 1980 50
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
Выводим строки в которых встречается сочетание букв ро
$ awk '/ро/ {print}' awk_test
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
то же самое
$ awk '/ро/ {}' awk_test
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
END и BEGIN
В AWK есть два оператора специального вида: BEGIN — начальные установки
и
END — действия, выполняемые после обработки последней записи входного потока.
BEGIN {действие}
шаблон {действие}
шаблон {действие}
. . .
END {действие}
Вызов AWK
Существуют два основных варианта:
- Первый
- awk [-Fc] 'script.awk' [файлы]
В этом случае программа заключенная в одинарные кавычки находятся в теле команды
-Fc — флаг, меняющий стандартный разделитель полей на c
файл — имя файла исходных данных, при его отсутствии данные читаются со стандартного входа.
Примеры:
$ cat awk_test | awk '/ро/ {print}'
и
$ awk '/ро/ {print}' < awk_test
дают результат, аналогичный
$ awk '/ро/ {print}' awk_test
Примеры, демонстрирующие обращение с тазделителями:
В этом примере команда выводит вторые($2) поля строк, содержащих ро
$ awk '/ро/ {print $2}' awk_test
А.П.
С.Л.
Л.Е.
В этом примере программа работает со строками, содержащими число 40, и использует в качестве разделителя полей цифру 9
$ awk -F9 '/40/ {print $2}' awk_test
78 40
7
- Второй
- awk [-Fc] -f script.awk [файлы]
Флаг -f указывает на awk-скрипт
Переменные и выражения
В языке awk выделяют две группы переменных:
- Предопределенные
- Декларированные в программе.
Исходные значения предопределенных переменных устанавливаются интерпретатором awk в процессе запуска и выполнения awk-программы.
К предопределенным относятся:
NR номер текущей строки; значение по-умолчанию NF число полей в текущей строке; RS разделитель строк на вводе; "\\0" FS разделитель полей на вводе; пробел и/или табуляция ORS разделитель строк на выводе; RS OFS разделитель полей на выводе; FS OFMT формат вывода чиcла; "%.6g" FILENAME имя входного файла.
Прочим переменным пользователь может присваивать начальные значения. По умолчанию "0" или пустая строка
Типы переменных:
- позиционные
- числа с плавающей точкой
- строка символов
- массив
Интерпретатор awk рассматривает переменную как строковую, пока не возникает необходимость выполнить операции:
- если пробел (конкатенация), то строки;
- если +, то числа с плавающей точкой.
Примеры:
$ awk '{a = $3 $4; print a}' awk_test
198050
197840
197940
197065
$ awk '{a = $3+$4; print a}' awk_test
2030
2018
2019
2035
$ awk '{} END{a = 2+ "2"; print a}' awk_test
4
$ awk '{} END{a = 2+2; print a}' awk_test
4
$ awk '{} END{a = 2+ "два"; print a}' awk_test
2
$ awk '{} END{a = "два" + "два"; print a}' awk_test
0
$ awk '{} END{a = 2.3+2.000; print a}' awk_test
4.3
Массив не объявляется, а начинает существовать в момент первого использования. Индекс массива — любое ненулевое значение или строка. Массивы ассоциативные, т.е. не по вычисляемому индексу, а по совпадению содержания, например:
day [Jan][31] = Mon day [Feb][01] = Tue day [Feb][02] = Wed
Массивы удобно использовать при суммированиях, например:
$ cat file
John 100
Mary 200
Mary 200
John 100
John 300
$
$ awk '{sum[$1] += $2; print $1 "_" sum[$1]}' file
John_100
Mary_200
Mary_400
John_200
John_500
Операции, подобные Си
=, +=, -=, *=, /=, %=, +, /, %, ++, --.
Сравнения чисел
<, <=, ==, !=, >=, >
Если хоть один аргумент - строка, то происходит сравнение строк.
Логические операции
!, ||, &&
Операция пробел - конкатенация.
Примеры awk-программ
$ awk '{print $2, $3}' awk_test
К.И. 1980
А.П. 1978
С.Л. 1979
Л.Е. 1970
$ awk '/е/ {print $2, $3}' awk_test
А.П. 1978
Л.Е. 1970
$ awk '/е/ {print $2, 2000-$3}' awk_test
А.П. 22
Л.Е. 30
$ awk '{ s = s + $4} END {print ("Суммарный возраст:" s);
print ("Средний возраст:" s/NR)}' awk_test
Суммарный возраст: 195
Средний возраст: 48.75
$ awk '{ s += $4 } {print("NR="NR, "NF="NF)}
END {print ("FILENAME=" FILENAME);
print ("Значение позиционной переменной" $4 "\"пусто\" после окончания просмотра)");
print ("Суммарный возраст:" s);
print ("Средний возраст:" s/NR)}' awk_test
NR=1 NF=4
NR=2 NF=4
NR=3 NF=4
NR=4 NF=4
FILENAME=awk_test
Значение позиционной переменной65"пусто" после окончания просмотра)
Суммарный возраст:195
Средний возраст:48.75
Селекторы
Здесь селектор — расширение понятия шаблон, поскольку там где в структуре команды указан шаблон, в общем случае может стоять любой селектор.
ЗАМЕЧАНИЕ — Открывающая скобка действия { должна быть в строке селектора.
В качестве селектора может быть:
- выражение
- шаблон
- их комбинация
Примеры:
выражение
$3 != $4 && $3 > 1970 $3 % 2 == 1 $1=="Иванов" - (кавычки, чтобы воспринималось, как строка.)
шаблон
/ab/ отлично от /a b/, / ab/ и /ab / номер_поля ^шаблон - по совпадению номер_поля !^шаблон - по несовпадению
$ awk '$3~0 {print}' awk_test
Иванов К.И. 1980 50
Федоров Л.Е. 1970 65
$ awk '$3!~0 {print}' awk_test
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Шаблон может формировать множество образцов или указывать, в каком месте поля искать:
- /^a/ --- поле начинается с a
- /a$/ --- поле кончается a
- \+ --- экранирует оператор +
- [abc] --- любой из символов a, b и c
- [a-р] --- любой символ диапазона
- * --- 0 или больше вхождений регулярного выражения
- + --- 1 или больше вхождений регулярного выражения
- ? --- 0 или 1 вхождение регулярного выражения
- ab|cd --- ab или cd
Примеры:
$ awk '$3~/(7[0-9])$/ {print}' awk_test
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
$ awk '$1=="Иванов" {print}' awk_test
Иванов К.И. 1980 50
$ awk '$4/2==25 {print}' awk_test
Иванов К.И. 1980 50
$ awk '$3 != $4 && $3 > 1970 {print}' awk_test
Иванов К.И. 1980 50
Петров А.П. 1978 40
Сидоров С.Л. 1979 40
$ awk '$1~/нов$/ {print}' awk_test
Иванов К.И. 1980 50
$ awk '/^Ив|дор/ {print}' awk_test
Иванов К.И. 1980 50
Сидоров С.Л. 1979 40
Федоров Л.Е. 1970 65
$ awk '/1980/,/1979/ {print}' awk_test
Иванов К.И. 1980 50
Петров А.П. 1978 40
Сидоров С.Л. 1979 40