GNU Awk


Введение

В современности awk в основном полезен тем, что разбивает текст в поданных ему строках на поля по заданному разделителю (по умолчанию разделитель — любое количество пробельных символов).

Например, в строке

    1   hi  7  2 3

Первое поле содержит 1, второе — hi, третье — 7 и так далее.

В силу того, насколько часто в Unix используются табличные данные в текстовом виде, полезно уметь получать конкретное поле.


cut

cut хорошо работает, если между полями заранее известное количество разделителей, например, в строке

1 2 3 4

В таком же случае, как выше, cut бесполезен. awk же позволяет взять конкретное поле; например, третье:

$ echo '    1   hi  7  2 3' | awk '{ print $3 }'
7

Именно такой вид имеет 99% вызовов awk (цифра с потолка).


gawk

Чуть сложнее вывести несколько полей разом:

$ echo '    1   hi  7  2 3' | awk '{ print $3, $2 }'
7 hi

Запятая важна. Можно её не писать, но тогда будет выведено не два поля по отдельности, а сконкатенированное содержимое двух полей:

$ echo '    1   hi  7  2 3' | awk '{ print $3 $2 }'
7hi

Светлый ум может предложить такой обходной путь:

$ echo '    1   hi  7  2 3' | awk '{ print $3 " " $2 }'
7hi

BEGIN

Это сработает, однако лучше пользоваться запятой, потому что awk дополнительно позволяет настраивать, каким символом разделять поля:

$ echo '    1   hi  7  2 3' | awk 'BEGIN { OFS=":" } { print $3, $2 }'
7:hi

Блок BEGIN позволяет написать команды, которые будут выполняться не для каждой строки, а один раз при запуске. Например, тогда имеет смысл установить переменные:

  • OFS: какой строкой разделять поля при выводе;
  • FS: по какой строке разбивать поля при чтении;
  • ORS и RS: чем разделяются записи при выводе и чтении соответственно; по умолчанию запись — это одна строка.

Блоки

В awk можно задать несколько блоков команд, и у каждого блока, как и у sed, можно указать условие, при котором блок исполнится:

$ cat /etc/passwd | awk 'BEGIN { FS=":"; OFS=";" }; /x/ {print $1, $2}; /y/ { print $0 }'

Здесь будут считываться строки и разбиваться на поля по двоеточию; затем, если в первой строке есть символ x, будут выведены первые два поля, разделённые ;; затем, если в ней есть символ y, будет выведена вся строка. Затем то же самое произойдёт для второй строки, затем для третьей, и так далее.


Что ещё

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

Скорее всего, это не понадобится в жизни, и того, что есть в примерах, достаточно для всех бытовых нужд.

Лучший способ понять awk — почитать info для gawk.