Язык обработки шаблонов AWK — часть 2

Действия

Простейшие операторы:

  • exit — завершить выполнение программы
  • next — перейти к следующей строке, управление на начало awk-программы
  • break — выход из цикла
  • continue — переход к следующей итерации

Структурные операторы:

  • if (условие) {операторы} [else {операторы}]
  • while (условие) {операторы}
  • for (выражение; условие; выражение) {операторы}
  • for (индекс in имя_массива) {операторы}

Структурные операторы в значительной степени аналогичны соответствующим операторам С.
В последнем случае для каждого индекса выполняется блок.
Текстовые индексы рассматриваются в лексикографическом порядке.

Примеры

$ awk '$4~/40/ {if($3<=1980) {print("Фамилия: " $1); M["40"]++}} $4~/50/ {M["50"]++} END {for(i in M) {print(" i =" i " M[" i "]=" M[i])}}' awk_test Фамилия: Петров Фамилия: Сидоров i =40 M[40]=2 i =50 M[50]=1 $ awk ' BEGIN {ORS = " "} { for(k=NF; k>0; --k) {print $k} {print RS} }' awk_test | sed 's/%$@~*!G4;:%#` //' 50 1980 К.И. Иванов 40 1978 А.П. Петров 40 1979 С.Л. Сидоров 65 1970 Л.Е. Федоров

Здесь, кроме изменения очередности полей в строке на противоположное (что делает цикл for), предварительно устанавливается выходной разделитель — пробел и весь результат предварительно выдается в одну строку, поэтому после обработки каждой строки выдается команда print RS для перевода выходной строки. С помощью sed убираем пробелы в начале строки.
Существенная деталь. Если запустить лишь базовую структуру

$ awk '{ for(k=NF; k>0; --k) {print $k}}' awk_test 50 1980 К.И. Иванов 40 1978 А.П. Петров 40 1979 С.Л. Сидоров 65 1970 Л.Е. Федоров

Однако, если поставим ; сразу после условия, т.е. сделаем пустое тело цикла, за пределы которого вынесен print $k, то получим исходную таблицу:

$ awk '{ for(k=NF; k>0; --k); {print $k}}' awk_test Иванов К.И. 1980 50 Петров А.П. 1978 40 Сидоров С.Л. 1979 40 Федоров Л.Е. 1970 65

поскольку $k после выхода из цикла будет иметь значение 0,

 а $0 — соответствует всей строке в качестве значения, то print $k будет после каждого цикла печатать полные строки.

Ввод и вывод данных

В общем случае в команде awk может быть указано несколько файлов.

awk [-Fc] 'script.awk' [file ...]
awk [-Fc] -f script.awk [file ...]

Файлы обрабатываются последовательно в указанном порядке.

Встроенные функции

  • sin (x) синус x
  • cos (x) косинус x
  • exp (x) возведение в степень x
  • log (x) натуральный логарифм x
  • sqrt (x) извлечение корня x
  • int (x) целая часть числа
  • length (s) длина строки s
  • printf (fmt, ...) форматирование(аналогично Си) по спецификации fmt.
  • substr (s, m, n) подстрока в n символов строки s,начинающаяся с m.
  • getline () чтение следующей строки.0 - конец файла, иначе 1.
  • index (s1, s2) номер позиции,с которой s1 совпадает с s2, иначе 0.
  • split (s, M, c) строка s разбивается элементы массива M по разделителю c (по умолчанию FS=" "); функция возвращает число полей.

Примеры

$ awk 'BEGIN {FS = "."; a=0} length ($1) > 8 { print (length ($1), $0); a++ } END {print ("Найдено строк: " a) }' awk_test 9 Сидоров С.Л. 1979 40 9 Федоров Л.Е. 1970 65 Найдено строк: 2

Здесь поля разделяются по ".", выбираются строки у которых длина первого поля больше 8-ми, и их длина length ($1) печатается перед строкой $0.

$ awk '{i=split($0, Name, "."); for (j=1; j<=i; j++) print ("Name[" j "]=" Name[j]) }' awk_test Name[1]=Иванов К Name[2]=И Name[3]= 1980 50 Name[1]=Петров А Name[2]=П Name[3]= 1978 40 Name[1]=Сидоров С Name[2]=Л Name[3]= 1979 40 Name[1]=Федоров Л Name[2]=Е Name[3]= 1970 65 $ awk '{print (length)}' awk_test 35 35 33 33

Поскольку все строки были выровнены пробелами, а в длине строки учитываются все символы до конца строки.

$ awk '{printf "%7.2f %s\n", NR, $0}' awk_test 1.00 Иванов К.И. 1980 50 2.00 Петров А.П. 1978 40 3.00 Сидоров С.Л. 1979 40 4.00 Федоров Л.Е. 1970 65 $ awk '{printf "\t%s %s \n", NR, $0}' awk_test 1 Иванов К.И. 1980 50 2 Петров А.П. 1978 40 3 Сидоров С.Л. 1979 40 4 Федоров Л.Е. 1970 65

//на основе статьи Соловьева А.