
Awk — это универсальный язык программирования, предназначенный для сложной обработки текста. Он в основном используется как инструмент для составления отчётов и анализа.
В отличие от большинства других процедурных языков программирования, awk работает с данными, то есть вы определяете набор действий, которые необходимо выполнить с входным текстом. Awk принимает входные данные, преобразует их и отправляет результат в стандартный поток вывода.
В этой статье рассматриваются основы языка программирования awk. Знание основ awk значительно улучшит ваши навыки работы с текстовыми файлами в командной строке.
Как работает awk
Существует несколько различных реализаций awk. Мы будем использовать GNU-реализацию awk, которая называется gawk. В большинстве систем Linux интерпретатор awk — это просто символическая ссылка на gawk .
Записи и поля
Awk может обрабатывать текстовые файлы и потоки данных. Входные данные разделяются на записи и поля. Awk обрабатывает одну запись за раз, пока не достигнет конца входных данных. Записи разделяются символом, называемым разделителем записей. Разделителем записей по умолчанию является символ новой строки, то есть каждая строка текстовых данных является записью. Новый разделитель записей можно задать с помощью переменной RS .
Записи состоят из полей, разделенных разделителем полей. По умолчанию поля разделяются пробелом, включающим один или несколько символов табуляции, пробела и новой строки.
Поля в каждой записи обозначаются знаком доллара ( $ ), за которым следует номер поля, начинающийся с 1. Первое поле обозначается $1 , второе — $2 и т. д. К последнему полю также можно обратиться с помощью специальной переменной $NF . На всю запись можно обратиться с помощью $0 .
Вот визуальное представление, показывающее, как ссылаться на записи и поля:
tmpfs 788M 1.8M 786M 1% /run/lock /dev/sda1 234G 191G 31G 87% / |-------| |--| |--| |--| |-| |--------| $1 $2 $3 $4 $5 $6 ($NF) --> fields |-----------------------------------------| $0 --> record
Программа Awk
Для обработки текста с помощью awk необходимо написать программу, которая сообщает команде, что делать. Программа состоит из набора правил и пользовательских функций. Каждое правило содержит одну пару «шаблон — действие». Правила разделяются символами новой строки или точкой с запятой ( ; ). Обычно программа на awk выглядит следующим образом:
pattern { action } pattern { action } ...
При обработке данных awk выполняет указанное действие, если запись соответствует шаблону. Если шаблон не задан, то сопоставляются все записи (строки).
Действие awk заключается в фигурные скобки ( {} ) и состоит из операторов. Каждый оператор определяет выполняемую операцию. Действие может состоять из нескольких операторов, разделённых символами новой строки или точкой с запятой ( ; ). Если правило не содержит действий, по умолчанию выводится вся запись.
Awk поддерживает различные типы операторов, включая выражения, условные операторы, операторы ввода, вывода и т. д. Наиболее распространённые операторы awk:
-
exit— останавливает выполнение всей программы и завершает работу. -
next— останавливает обработку текущей записи и переходит к следующей записи во входных данных. -
print— печать записей, полей, переменных и пользовательского текста. -
printf— предоставляет больше контроля над форматом вывода, аналогично C и bashprintf.
При написании программ на awk всё после символа решётки (#) и до конца строки считается комментарием. Длинные строки можно разбить на несколько строк с помощью символа продолжения — обратной косой черты ( ).
Выполнение программ awk
Программу awk можно запустить несколькими способами. Если программа короткая и простая, её можно передать интерпретатору awk непосредственно в командной строке:
awk 'program' input-file...
При запуске программы в командной строке ее следует заключать в одинарные кавычки ( '' ), чтобы оболочка не интерпретировала программу.
Если программа большая и сложная, лучше всего поместить ее в файл и использовать опцию -f для передачи файла команде awk :
awk -f program-file input-file...
В приведенных ниже примерах мы будем использовать файл с именем «teams.txt», который выглядит следующим образом:
Bucks Milwaukee 60 22 0.732 Raptors Toronto 58 24 0.707 76ers Philadelphia 51 31 0.622 Celtics Boston 49 33 0.598 Pacers Indiana 48 34 0.585
Шаблоны Awk
В awk вы можете контролировать, следует ли выполнять соответствующее действие, используя шаблоны.
Awk поддерживает различные типы шаблонов, включая регулярные выражения, выражения отношений, диапазоны и специальные шаблоны выражений.
Если правило не содержит шаблона, проверяется каждая входная запись. Вот пример правила, содержащего только действие:
awk '{ print $3 }' teams.txt
Программа выведет третье поле каждой записи:
60 58 51 49 48
Шаблоны регулярных выражений
Регулярное выражение (regular expression) — это шаблон, соответствующий набору строк. Шаблоны регулярных выражений Awk заключаются в косые черты ( // ):
/regex pattern/ { action }
Самый простой пример — сопоставление литеральных символов или строк. Например, чтобы отобразить первое поле каждой записи, содержащее «0,5», выполните следующую команду:
awk '/0.5/ { print $1 }' teams.txt
Celtics Pacers
Шаблон может быть любым типом расширенного регулярного выражения. Вот пример, который выводит первое поле, если запись начинается с двух или более цифр:
awk '/^[0-9][0-9]/ { print $1 }' teams.txt
76ers
Модели реляционных выражений
Шаблоны реляционных выражений обычно используются для сопоставления содержимого определенного поля или переменной.
По умолчанию шаблоны регулярных выражений сопоставляются с записями. Чтобы сопоставить регулярное выражение с полем, укажите поле и используйте оператор сравнения «contain» ( ~ ) с шаблоном.
Например, чтобы напечатать первое поле каждой записи, второе поле которой содержит «ia», необходимо ввести:
awk '$2 ~ /ia/ { print $1 }' teams.txt
76ers Pacers
Чтобы сопоставить поля, не содержащие заданный шаблон, используйте оператор !~ :
awk '$2 !~ /ia/ { print $1 }' teams.txt
Bucks Raptors Celtics
Вы можете сравнивать строки или числа по таким параметрам, как «больше», «меньше», «равно» и т. д. Следующая команда выводит первое поле всех записей, третье поле которых больше 50:
awk '$3 > 50 { print $1 }' teams.txt
Bucks Raptors 76ers
Модели диапазона
Шаблоны диапазонов состоят из двух шаблонов, разделенных запятой:
pattern1, pattern2
Сопоставляются все записи, начиная с записи, соответствующей первому шаблону, и до записи, соответствующей второму шаблону.
Вот пример, который выведет первое поле всех записей, начиная с записи, включающей «Рэпторс», до записи, включающей «Селтикс»:
awk '/Raptors/,/Celtics/ { print $1 }' teams.txt
Raptors 76ers Celtics
Шаблоны также могут быть выражениями отношений. Команда ниже выведет все записи, начиная с той, чьё четвёртое поле равно 32, и до той, чьё четвёртое поле равно 33:
awk '$4 == 31, $4 == 33 { print $0 }' teams.txt
76ers Philadelphia 51 31 0.622 Celtics Boston 49 33 0.598
Шаблоны диапазонов нельзя комбинировать с другими выражениями шаблонов.
Специальные шаблоны выражений
Awk включает следующие специальные шаблоны:
-
BEGIN— используется для выполнения действий перед обработкой записей. -
END— используется для выполнения действий после обработки записей.
Шаблон BEGIN обычно используется для установки переменных, а шаблон END — для обработки данных из записей, например вычислений.
В следующем примере будет напечатано «Начать обработку», затем третье поле каждой записи и, наконец, «Завершить обработку».
awk 'BEGIN { print "Start Processing." }; { print $3 }; END { print "End Processing." }' teams.txt
Start Processing 60 58 51 49 48 End Processing.
Если в программе есть только шаблон BEGIN , действия выполняются, а входные данные не обрабатываются. Если в программе есть только шаблон END , входные данные обрабатываются до выполнения действий правила.
Gnu-версия awk также включает два дополнительных специальных шаблона: BEGINFILE и ENDFILE , которые позволяют выполнять действия при обработке файлов.
Комбинирование узоров
Awk позволяет объединять два или более шаблонов с помощью логического оператора И ( && ) и логического оператора ИЛИ ( || ).
Вот пример, в котором оператор && используется для печати первого поля тех записей, у которых третье поле больше 50, а четвертое поле меньше 30:
awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt
Bucks Raptors
Встроенные переменные
В Awk есть ряд встроенных переменных, которые содержат полезную информацию и позволяют управлять обработкой программы. Ниже приведены некоторые из наиболее распространённых встроенных переменных:
-
NF— Количество полей в записи. -
NR- Номер текущей записи. -
FILENAME— имя входного файла, который в данный момент обрабатывается. -
FS— Разделитель полей. -
RS- Разделитель записей. -
OFS- Разделитель выходных полей. -
ORS- Разделитель выходных записей.
Вот пример, показывающий, как вывести имя файла и количество строк (записей):
awk 'END { print "File", FILENAME, "contains", NR, "lines." }' teams.txt
File teams.txt contains 5 lines.
Переменные в AWK можно устанавливать в любой строке программы. Чтобы определить переменную для всей программы, добавьте её в шаблон BEGIN .
Изменение поля и разделителя записей
Значение разделителя полей по умолчанию — любое количество пробелов или символов табуляции. Его можно изменить, задав значение в переменной FS .
Например, чтобы установить разделитель полей на . вы должны использовать:
awk 'BEGIN { FS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0 Raptors Toronto 58 24 0 76ers Philadelphia 51 31 0 Celtics Boston 49 33 0 Pacers Indiana 48 34 0
В качестве разделителя полей также можно задать более одного символа:
awk 'BEGIN { FS = ".." } { print $1 }' teams.txt
При запуске однострочных команд awk в командной строке вы можете использовать опцию -F для изменения разделителя полей:
awk -F "." '{ print $1 }' teams.txt
По умолчанию разделителем записей является символ новой строки и может быть изменен с помощью переменной RS .
Вот пример, показывающий, как изменить разделитель записей на . :
awk 'BEGIN { RS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0 732 Raptors Toronto 58 24 0 707 76ers Philadelphia 51 31 0 622 Celtics Boston 49 33 0 598 Pacers Indiana 48 34 0 585
Действия Awk
Действия Awk заключаются в фигурные скобки ( {} ) и выполняются при совпадении с шаблоном. Действие может содержать ноль или более операторов. Несколько операторов выполняются в порядке их появления и должны быть разделены символами новой строки или точкой с запятой ( ; ).
В awk поддерживаются несколько типов операторов действий:
- Выражения, такие как присваивание переменных, арифметические операторы, операторы увеличения и уменьшения.
- Управляющие операторы, используемые для управления ходом программы (
if,for,while,switchи т. д.) - Операторы вывода, такие как
printиprintf. - Составные высказывания для группировки других высказываний.
- Операторы ввода для управления обработкой ввода.
- Операторы удаления для удаления элементов массива.
Оператор print , пожалуй, наиболее используемый оператор awk. Он выводит форматированный вывод текста, записей, полей и переменных.
При печати нескольких элементов необходимо разделять их запятыми. Вот пример:
awk '{ print $1, $3, $5 }' teams.txt
Печатные элементы разделяются одинарными пробелами:
Bucks 60 0.732 Raptors 58 0.707 76ers 51 0.622 Celtics 49 0.598 Pacers 48 0.585
Если не использовать запятые, между элементами не будет пробела:
awk '{ print $1 $3 $5 }' teams.txt
Печатные элементы объединяются:
Bucks600.732 Raptors580.707 76ers510.622 Celtics490.598 Pacers480.585
Если print используется без аргумента, по умолчанию print $0 . Печатается текущая запись.
Чтобы напечатать пользовательский текст, необходимо заключить его в двойные кавычки:
awk '{ print "The first field:", $1}' teams.txt
The first field: Bucks The first field: Raptors The first field: 76ers The first field: Celtics The first field: Pacers
Вы также можете печатать специальные символы, такие как перевод строки:
awk 'BEGIN { print "First linenSecond linenThird line" }'
First line Second line Third line
Оператор printf даёт больше контроля над форматом вывода. Вот пример, вставляющий номера строк:
awk '{ printf "%3d. %sn", NR, $0 }' teams.txt
printf не создает новую строку после каждой записи, поэтому мы используем n :
1. Bucks Milwaukee 60 22 0.732 2. Raptors Toronto 58 24 0.707 3. 76ers Philadelphia 51 31 0.622 4. Celtics Boston 49 33 0.598 5. Pacers Indiana 48 34 0.585
Следующая команда вычисляет сумму значений, хранящихся в третьем поле каждой строки:
awk '{ sum += $3 } END { printf "%dn", sum }' teams.txt
266
Вот еще один пример, показывающий, как использовать выражения и управляющие операторы для печати квадратов чисел от 1 до 5:
awk 'BEGIN { i = 1; while (i < 6) { print "Square of", i, "is", i*i; ++i } }'
Square of 1 is 1 Square of 2 is 4 Square of 3 is 9 Square of 4 is 16 Square of 5 is 25
Однострочные команды, подобные приведённой выше, сложнее понимать и поддерживать. При написании более длинных программ следует создавать отдельный программный файл:
prg.awk
BEGIN { i = 1 while ( i < 6 ) { print "Square of" , i , "is" , i * i ; ++ i } }
Запустите программу, передав имя файла интерпретатору awk :
awk -f prg.awk
Вы также можете запустить программу awk как исполняемый файл, используя директиву shebang и настроив интерпретатор awk :
prg.awk
#!/usr/bin/awk -f BEGIN { i = 1 while ( i < 6 ) { print "Square of" , i , "is" , i * i ; ++ i } }
Сохраните файл и сделайте его исполняемым :
chmod +x prg.awk
Теперь вы можете запустить программу, введя:
./prg.awk
Использование переменных оболочки в программах Awk
Если вы используете команду awk в скриптах оболочки, вам, скорее всего, потребуется передать переменную оболочки в программу awk. Один из вариантов — заключить программу в двойные кавычки вместо одинарных и подставить переменную в программу. Однако этот вариант усложнит вашу программу awk, поскольку вам придётся экранировать переменные awk.
Рекомендуемый способ использования переменных оболочки в программах awk — присваивание переменной оболочки переменной awk. Вот пример:
num=51awk -vn="$num" 'BEGIN {print n}'
51
Заключение
Awk — один из самых мощных инструментов для работы с текстом.
Эта статья лишь поверхностно описывает язык программирования awk. Чтобы узнать больше об awk, ознакомьтесь с официальной документацией Gawk .
Если у вас есть вопросы или пожелания, не стесняйтесь оставлять комментарии.
Связанные руководства