Команда awk

Команда awk позволяет работать с утилитой для обработки строк. Например, эта утилита может извлечь лишь второй столбец из текстового файла с данными в табличном формате. awk по своей сути является не простой утилитой, а полноценной реализацией языка программирования. Утилиты awk и gawk (GNU awk) являются равноценными в плане функций.

Практическое применение

awk может как принимать входные данные от программы, так и читать их из файла. Инструкции awk могут либо передаваться утилите с помощью командной оболочки, либо помещаться в текстовый файл, имя которого должно передаваться утилите после параметра -f. По умолчанию входные данные читаются из файлов, имена которых передаются утилите в качестве аргументов, а если их не передается — из стандартного потока ввода. В первом примере инструкции awk передаются утилите с помощью командной оболочки, а входные данные читаются из файла; во втором примере для генерации входных данных используется внешняя программа, эти данные передаются awk посредством программного канала, а все инструкции размещаются во внешнем файле сценария:

$ awk '{ print $1; }' datafile

$ makedata | awk -f myscript.awk

Сценарии awk в формате отдельных файлов могут делаться исполняемыми путем размещения корректной последовательности «шебанг» в их первых строках:

#!/bin/awk -f

Важное замечание: в том случае, если утилита awk расположена не по пути /bin/awk, вам придется использовать корректный путь к данной утилите (который можно получить путем исполнения команды which awk).

Примеры использования

Объединение содержимого файлов с пропуском некоторых столбцов

cat >file_1<<eof
O11 0.081
O12 0.341
O13 0.343
eof

cat >file_2<<eof
O11 0.105
O12 0.415
O13 0.327
eof

paste file_1 file_2 | awk '{print $1" "$2" "$4}'
O11 0.081 0.105
O12 0.341 0.415
O13 0.343 0.327

Последняя команда предназначена для объединения содержимого файлов с пропуском третьего столбца.

Структура языка программирования

Программа на awk состоит из наборов инструкций, каждая из которых состоит из описаний шаблона и действия. awk осуществляет автоматическое построчное чтение входных данных (либо из файлов, либо из стандартного потока ввода). Если заданный шаблон соответствует строке, выполняется заданное действие. При этом существует несколько специальных шаблонов. Инструкция BEGIN исполняется в первую очередь до чтения каких-либо входных данных, а иснтрукция END — в последнюю очередь после обработки всех входных данных.

Некоторые сложные сценарии на awk состоят лишь из правила BEGIN и инструкции getline для чтения входных данных. В том случае, если шаблон не задан, действие выполняется всегда. Если же не задано действие, awk будет просто выводить строки.

В качестве шаблона может использоваться регулярное выражение, экранированное с помощью символов слэша («/»), причем соответствие входной строки данному регулярному выражению (то есть, наличие в этой строке соответствующего ему текста) будет равносильно соответствию этой строки шаблону. Регулярное выражение /^[^#]/ позволяет получить все строки, не начинающиеся с символа решетки. Также шаблон может быть представлен в форме выражения awk (такого, как выражение NF>5, предназначенное для получения всех строк, содержащих более 5 слов).

Каждый раз после чтения строки (либо в автоматическом режиме, либо с помощью инструкции getline) происходит ее разделение на отдельные слова. Первое слово ставится в соответствие выражению $1, второе — выражению $2 и так далее. Данная особенность работы awk упрощает работу со столбцами данных. Переменная NF содержит число слов в строке. Символ $ является оператором языка awk, следовательно, он может использоваться в рамках любых выражений. Например, выражение $NF соответствует последнему слову строки.

Мощь языка awk заключается в возможности использования динамических массивов, особенно в комбинации с регулярными выражениями. Это обстоятельство позволяет создавать сложные запросы для обработки множества файлов со сбором и сравнением результатов, аналогичные приведенному ниже запросу, позволяющему установить: «Какими являются первые слова всех строк и насколько часто они используются?».

В следующем примере демонстрируются некоторые мощные возможности языка awk:

  • получение строк, не начинающихся с символа #
  • разделение полученных строк на слова
  • использование каждого слова в качестве индекса в массиве количества слов (wordcount)
  • инструкция END с вычислением количества слов после обработки всех входных данных
  • сортировка индексов с помощью вызова asorti() и вывод результатов расчетов

/^[^#]/{
  w=match($0,/([a-zA-Z0-9_$]+)/,thisline);
  for(i=1; i<=w; i++) {
    wordcounts[toupper(thisline[i])]++;
  }
}
END {
  n = asorti(wordcounts, words);
  for (i = 1; i <= n; i++) {
    printf("%14s - %4dn",words[i],wordcounts[words[i]]);
  }
}

Если вы сохраните приведенные выше инструкции в файле с расширением .awk, вы сможете применить их по отношению к группе текстовых файлов с помощью команды:

awk -f words.awk *.txt

Теперь вы можете самостоятельно добавить более сложное регулярное выражение, использовать инструкцию printf() для отладки, создать несколько массивов для хранения результатов, использовать инструкцию split() для оптимизации процесса разбора текста, а также рассмотреть другие возможности awk, которые делают этот язык одним из самых мощных языков сценариев.

Более полное описание возможностей языка доступно в руководстве по работе с gawk.

Расширения GNU Awk

Вы не должны использовать следующие инструкции и механизмы при исполнении сценариев для gawk с помощью awk:

  • Специальные файлы, такие, как /dev/stderr, часто используемые для вывода сообщения об ошибках.
  • Функции systime() и strftime().
  • Инструкция nextfile.
  • Инструкция delete ARRA, часто используемая для удаления всего массива.
  • Функция gensub(),
  • Двунаправленные программные каналы для, часто используемые для взаимодействия с сопроцессами.

Данный список не является исчерпывающим; на странице руководства gawk приведен больший объем информации.