Си-подобный текстовый процессор AWK

в 18:35, , рубрики: awk, linux, поисковая оптимизация, Си, метки: , , ,

В данной статье будут представлены основные возможности языка AWK, сопровождаемые примерами. Также будет затронут вопрос о области его использования. Данная публикация носит ознакомительный характер. Ну что ж, поехали…

Немного истории

Самая первая версия AWK была создана корпорацией Bell Laboratories в 1977г. Название AWK означает инициалы его создателей Alfred Aho, Peter Weinberger и Brian Kernighan. Хотелось бы отметить, что в данном языке прослеживается влияние С, SNOBOL4 и Bourne Shell. Предназначен для обработки символьных и числовых полей в записях структурированных текстов.

Структура программ, написанных на AWK

Программы на AWK обычно состоят из нескольких ключевых блоков, которыми являются BEGIN block, body block и END block. Необязательно, чтобы присутствовали все блоки. А теперь немного поподробнее о каждом из них.

BEGIN block

Синтаксис:
BEGIN { awk-command }
Данный блок выполняется только один раз за все время работы программы. Основное предназначение это инициализация переменных. Как ранее было отмечено, допускается отсутствие данного блока.

body block

Синтаксис:
/pattern/ { action }
Данный блок выполняется интерпретатором awk один раз для каждой записи ( строки ) обрабатываемого файла. Допустим, если файл содержит 100 записей ( строк ), то данный блок будет выполнен 100 раз для каждой записи ( строки ) отдельно. /pattern/ не является обязательным. Если /pattern/ не будет указан, awk будет обрабатывать все записи из входного файла. Если же будет задан /pattern/, то тогда обработке будут переданы лишь те записи из входного файла, которые соответствуют данному шаблону. { action } является командой, которая будет применена к каждой строке, соответствующей шаблону. Примером { action } может быть print.

END block

Синтаксис:
END { awk-command }
Данный блок выполняется только один раз в самом конце после body block. END block обычно используется для генерирования отчета.

Самое время привести примеры

Пусть тем самым структурированным файлом для awk будет employee.txt, содержимое которого:
Jane Li, IT Manager, 3000
Kate Moon, Nurse, 2000
Steve Zima, Writer, 4250
Andrew Sky, Policeman, 4000

Кстати, обращаю внимание, что в данном файле информация структурирована: у всех записей первое поле это имя фамилия, второе — должность, третье — зарплата.

Для начала выполним простую команду в консоли Linux для вывода всего содержимого:

$ awk {print} employee.txt

Так как не было задано того самого шаблона ( /pattern/ ) интерпретатор вывел все содержимое файла employee.txt.
А теперь выведем в консоль информацию о сотрудниках, получающих зарплату выше либо равную 3000 ( у.е ):

$ awk 'BEGIN { FS="," } {if( $3 >= 3000) print $0 }' employee.txt

FS ( от file separator ) — встроенная переменная, которая хранит по умолчанию пробел в качестве сепаратора полей. В данном примере, значение "," переменной FS гарантирует разбиение каждой записи на три поля. Доступ к полям осуществляется с помощью переменных $1, $2, $3. Кстати $0 означает целую запись со всеми полями.
В следующем примере посчитаем, сколько составляют прямые затраты фирмы на зарплату:

$ awk 'BEGIN { FS=","; total=0 } {total+=$3;print } END { printf( ''total=$%dn'',total)}' employee.txt

Кстати, print без аргументов означает всего навсего печать целой записи, т.е. $0. AWK немного особенный язык по сравнению с С, т.к. вовсе не обязывет к декларации и инициализации переменной. Т.е. следующие примеры идентичны по отношению к последнему:

$ awk 'BEGIN { FS=","; total } {total+=$3;print } END { printf( ''total=$%dn'',total)}' employee.txt
$ awk 'BEGIN { FS="," } {total+=$3;print } END { printf( ''total=$%dn'',total)}' employee.txt

Циклы

Что касается циклов, то здесь все предельно понятно. AWK поддерживает while, do-while и for циклы. Синтаксис традиционный. Например:

$ awk 'BEGIN { while(i<17){ str=str "#";i++} print str }'

str=str "#" — ничто инное как конкатенация.
Кстати, в awk не забыто и о предназначении break, exit, continue.
Иногда приходится писать очень много строк кода для получения ожидаемого результата. Совершенно понятно, что консоль уже не будет тем местом, где удобно было бы писать n десятков строк того самого кода. Эту проблему легко обойти. Достаточно структурную часть AWK записать в файл, и при необходимости обратиться к нему. Последний пример можно было бы выполнить следующим образом:
в файле script.awk сохранить следующее:

BEGIN { while(i<17){ str=str "#";i++} print str }

Чтобы запустить последний пример:

$ awk -f script.awk

Ассоциативные массивы

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

$ awk 'BEGIN { arr[1]=«a»; arr[2]=2; arr[«n»]=777; for( i in arr ) print arr[i] }'

Заключение
В данной статье я старался показать поверхностные возможности мощного текстового процессора AWK. Такие важные аспекты, как работа со строками, работа с ассоциативными массивами, заслуживает большего внимания и является хорошей темой следующих публикаций. Поэтому я их целенаравленно оставил на потом. Надеюсь, что моя первая статья намного приблизила всем прочитавшим ее некоторые возможности невсем известного AWK.

Литература

1. Sed & Awk 101 Hacks
2. The Awk Programming Language by Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger

Автор: nedved

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js