Введение
Awk — это универсальный язык сценариев, разработанный для расширенной обработки текста. Он в основном используется в качестве инструмента отчетности и анализа.
В отличие от большинства других процедурных языков программирования, awk управляется данными, что означает, что вы определяете набор действий, которые должны выполняться по отношению к входному тексту. Он принимает входные данные, преобразует их и отправляет результат на стандартный вывод.
В этой статье рассматриваются основы языка программирования awk. Знание основ awk значительно улучшит вашу способность манипулировать текстовыми файлами из командной строки.
Как работает Авк
Существует несколько реализаций awk. Мы будем использовать реализацию awk GNU, которая называется 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
Схемы регулярных выражений
Регулярное выражение или регулярное выражение — это шаблон, который соответствует ряду строк. Шаблоны регулярных выражений 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
Схемы реляционных выражений
Шаблоны реляционных выражений обычно используются для сопоставления содержимого определенного поля или переменной.
По умолчанию шаблоны регулярных выражений сравниваются с записями. Чтобы сопоставить регулярное выражение с полем, укажите поле и используйте оператор сравнения «содержать» ~
.
Например, чтобы напечатать первое поле каждой записи, второе поле которой содержит «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
Все записи, начиная с записи, соответствующей первому шаблону, до тех пор, пока не будет найдена запись, соответствующая второму шаблону.
Вот пример, который напечатает первое поле всех записей, начиная с записи, включающей «Raptors», до записи, включающей «Celtics»:
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
, ввод обрабатывается перед выполнением действий правила.
Версия awk для Gnu также включает две другие специальные схемы , BEGINFILE
позволяющие ENDFILE
выполнять действия при обработке файлов.
Комбинация моделей
Awk позволяет комбинировать два или более шаблона с помощью логического &&
оператора И и логического оператора ИЛИ ||
.
Вот пример, который использует оператор &&
для печати первого поля тех записей, третье поле которых больше 50, а четвертое поле меньше 30:
awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt
76ers Philadelphia 51 31 0.622
Celtics Boston 49 33 0.598
Интегрированные переменные
В 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
другие )whileswitch
- Объявления вывода, такие как
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 line\nSecond line\nThird line" }'
First line
Second line
Third line
Оператор printf
дает вам больше контроля над выходным форматом. Вот пример, который вставляет номера строк:
awk '{ printf "%3d. %s\n", 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 "%d\n", 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
Однострочные команды, подобные приведенной выше, труднее понять и поддерживать. При написании более длинных программ необходимо создать отдельный файл программы:
Запустите программу, передав имя файла интерпретатору awk
:
awk -f prg.awk
Вы также можете запустить программу awk как исполняемый файл, используя директиву shebang и установив интерпретатор awk
:
Сохраните файл и сделайте его исполняемым с помощью команды chmod :
chmod +x prg.awk
Теперь вы можете запустить программу, введя:
./prg.awk
Использование переменных оболочки в программах Awk
Если вы используете команду awk
в сценариях оболочки, скорее всего, вам потребуется передать переменную оболочки в программу awk. Один из вариантов — заключить программу в двойные, а не в одинарные кавычки и заменить переменную в программе. Однако эта опция сделает вашу awk-программу более сложной, так как вам придется экранировать переменные awk.
Рекомендуемый способ использования переменных оболочки в программах awk — присвоить переменную оболочки переменной awk. Вот пример:
num=51
51
Вывод
Awk — один из самых мощных инструментов для работы с текстом. Чтобы узнать больше о awk, ознакомьтесь с официальной документацией Gawk .