Язык обработки шаблонов 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 

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