AWK - утилита предназначенная для простых, механических и вычислительных манипуляций над данными. Довольно несложные операции часто необходимо выполнить над целыми пакетами файлов, а писать для этого программу на одном из стандартных языков программирования является утомительным и, как правило, не очень простым делом. Оптимальное решение проблемы - использование специальной утилиты AWK, включающей в себя не громоздкий и удобный язык программирования, позволяющий решать задачи обработки данных с помощью коротких программ, состоящих из двух-трех строк.
Утилита AWK изначально объединяла свойства утилит UNIX - sed и grep. В дальнейшем ее возможности значительно расширились. Утилита AWK была создана в 1977г, американскими авторами: Alfred V.Aho, Brian W.Kernighan и Peter J.Weinberger.
AWK сканирует input (стандартный или указываемый набор файлов), и над строками, удовлетворяющими заданному образцу, выполняет указываемые действия. Строка может содержать максимально до 256 символов.
Формат:
AWK [-Fc] [-f file] [files]
AWK [-Fc] [prog] [files]
prog - программа, вида: ' образец ${$действие$}$'
file - файл с AWK-программой:
образец { действие}
образец { действие}
...
files - файлы, предназначенные для AWK-обработки.
-Fc - устанавливает разделитель полей в "с" (См. 1.2.1 и 2.4)
2. Образец:
3. Действие:
Предложение:
На поля можно ссылаться из AWK программы следующим образом:
Строка может содержать максимально до 100 полей.
x = 1, x воспринимается как число;
x = " ", x - строка;
x + "abc" - результат операции интерпретируется как число независимо от того, было ли х числом или строкой. Если строка не может быть интерпретирована как число ("abc"), то ее значение становится 0.
Строка может содержать максимально до 256 символов.
Например:
box="4" (присваиваем box значение строки 4)
box=box*4 (box получила значение 16, но уже не как строка, а как число)
box=box"коробок конфет" (наша переменная box является строковой со значением "16 коробок конфет")
Вообще AWK в состоянии при преобразовании строки в число распознать такие строки: "100","1n00","100fg" как число 100.
$1 = "3" + $2 - первое поле принимает значение второго поля, увеличенного на 3.
$(i+1) - интерпретируется как поле, номер которого зависит от значения переменной i.
x[NR] = $0 - элементу массива x, индексированному NR, присваивается обрабатываемая строка.
x["apple"] - элементы массива могут индексироваться не числовым значением, т.е. строкой.
< Операция> : "+", "-", "*", "/", "%"
| "()" | - Скобки допускаются для группирования; |
| "|" | - Указание альтернативы "или"; |
| "+" | - Плюс, стоящий за регулярным выражением означает любую последовательность вхождений этого выражения, начиная с 1; |
| "?" | - Знак вопроса за регулярным выражением означает 0 или 1 вхождений этого выражения; |
| "[]" | - описывает множества единичных символов. (описывают простым перечислением); |
| "-" | -используется для задания диапазона символов, соответствующего таблице кодов ASCII. |
| "~" | - тильда соответствует началу строки (/~A/ соответствует строкам начинающиеся на А) |
| "$" | - знак доллара соответствует концу строки (/A$/ соответствует строкам заканчивающиеся на А) |
| "." | - точка обозначает произвольный единичный символ. |
| "*" | - как и + соответствует многократному повторению предыдущего символа, но возможно и нулевое вхождение |
| "\" | - отменяет специальное значение символа (\. означает точку) |
Например:
/Olga/ - Указывает на строки, содержащие Olga.
/[Oo]lga|[Mm]ike|[Mm]al/ - Указывает на строки, содержащие Olga или olga или Mike или mike или Mal или mal.
/number[0-9]/ - Указывает на строки, содержащие number0 или number1 или ... number9.
/\/.+\// - Указывает на строки, содержащие любое количество символов, больше или равное 1, заключенных в / /.
Логические операции
| "||" | - логическое или|
| "&&" | - логическое и|
| "<,<=" | - меньше, меньше или равно |
| ">=,>" | - больше или равно, больше |
| "==" | - численное равенство или совпадение строк |
| "!" | - отрицание |
| "~" | - проверка на содержание |
Например:
$1 ~ /[Oo]lga/ - Указывает на строки, первое поле которых содержит Olga или olga.
$1 > = "s" - Указывает на строки, начинающиеся с символа s или следующих за ним по порядку: t, u, v...
Последовательности образцов, соединенных одним из знаков читаются слева направо.
Комбинация: ''образец1, образец2'' указывает, что действие выполняется над строками, попадающими в указанный ранг: то есть, начиная от строки, удовлетворяющей ''образец1" и вплоть до строки, удовлетворяющей ''образец2", включая ее саму.
Например:
/02\.95/ & & ($1 !~ /\.su/ $2 !~ /\.su/) - Указывает на строки, содержащие 02.95 и не имеющие .su одновременно в первом и во втором поле.
NR == 100, NR == 200 - Указывает строки с номерами от 100 до 200.
Образец BEGIN указывает на начало input или на те действия, которые должны быть выполнены до какого бы то ни было анализа строк. Образец END указывает на конец input или на те действия, которые должны быть выполнены после обработки всех строк.
Например:
BEGIN {FS = ":"} - Устанавливает разделитель полей в ":" до начала обработки строк. Эквивалентно опции "-F:" при AWK вызове.
END { print NR } - Печатает номер последней строки input, т.е. количество обработанных входных строк.
По умолчанию AWK читает с устройства стандартного ввода (клавиатура), однако может читать и подготовленный заранее файл данных или конвейерный вывод другой программы. В строке вызова AWK можно указать несколько файлов данных, AWK будет последовательно их обрабатывать. Имя текущего файла ввода доступно как значение переменной FILENAME Эти базовые возможности AWK по вводу данных могут быть существенно расширены использованием функции (или команды) getline Использованная без аргументов, getline просто читает очередную запись из текущего файла ввода. Это позволяет, например, специальным образом обработать следующую строку, если вы, например, обнаружили во входных данных сообщение типа:
"TOP SECRET! NEXT LINE TO BE BURNED BEFORE READING"
После выполнения команды getline AWK продолжает нормальный цикл своей деятельности, применяя к этой записи последующие пары образец - действия. Команда getline может быть использована для ввода, значения строковой переменной:
getline message:
Никаких побочных эффектов при этом не происходит, за исключением того, что изменяется счетчик записей NR. Команда getline может читать из поименованного файла, используя технику перенаправления:
getline < file
Выражение file может быть произвольным строковым выражением, которое интерпретируются как имя файла в данной операционной системе. Если getline не встретила каких-либо проблем при исполнении, она возвращает значение 1. Если при исполнении обнаружен конец файла, то возвращается 0, если обнаружена ошибка, то возвращается -1. В последнем случае причину ошибки можно найти, проанализировав значение переменной ERRNO.
Формат оператора печати:
PRINT [< список выражений> ] [ > < выражение1> ]
Если в списке выражения находятся через запятую(,), то значения этих выражений выводятся на output (печатаются) через символ-разделитель OFS (по умолчанию пробел).
Например: команда print "Вася","+","Маша" выдаст Вася + Маша.
Если же выражения стоят через пробел, то на печати происходит их конкатенация.
Значение < выражение1> рассматривается как имя файла. Само его присутствие означает печать в файл. Если вместо "> " стоит "> > ", то это означает добавление к уже существующему файлу. Можно использовать в одной программе максимально до 10 output файлов.
Оператор форматированной печати:
PRINTF формат [список выражений] [ > выражение1]
формат: символьная строка в двойных кавычках. Идентичен формату, используемому в функции printf в языке ''С''. Формат может содержать:
Стандартные правила:
| %s | - строка символов |
| %d | - десятичное число |
| %f | -вещественное число с десятичной точкой |
| %o | - восьмеричное число |
| %x | - шестнадцатеричное число |
Программа AWK допускает также и перенаправление вывода в конвейер. В этом случае оператор вывода имеет вид:
printf A,B,B,...|CMD, где команда CMD может быть произвольным строковым выражением. Значение этого выражения передается командному интерпретатору операционной системы для исполнения. Опять же напомним, что в AWK желательно после обработки одного файла сразу же его закрыть, хотя AWK в состоянии поддерживать 10 открытых файлов.
Команды закрытия:
close (filemane) - закрытие файла filename
close (command) - закрытие конвейера command
< переменная> = < выражение>
Начальное значение переменной 0 или " " (пробел). Допускаются другие типы присваивания в соответствии с языком ''С'': "+=","-=","*=","/=","%=".
< переменная> ++, ++< переменная> - увеличение значения переменной на 1.
< переменная> --, --< переменная> - уменьшение значения переменной на 1.
| atana2() | - арктангенс |
| cos() | - косинус |
| exp(),log(),sqrt() | - Математические функции экспонента, логарифм и квадратный корень. |
| gsub(s,t,u) | - аналогична sub, но заменяет все вхождения t |
| index(s,t) | - Возвращает начальную позицию подстроки t в строке s. (Или 0, если t в s не содержится.) |
| int() | - Функция целой части числа. |
| length(arg) | - Функция длины arg. Если arg не указан, то выдает длину текущей строки. |
| match(s,t) | - проверка на наличие подстроки t в строке s |
| rand | - псевдослучайное число из интервала [0,1] |
| split(s,array,sep) | - Помещает поля строки s в массив array и возвращает число заполненных элементов массива. Если указан sep, то при анализе строки он понимается как разделитель. |
| sprintf(fmt,exp1,exp2,...) | - Осуществляет форматированную печать (вывод) в строку, идентично PRINTF. |
| srand | - инициализация случайного датчика |
| strtime(firmat,time) | - возвращает строковое значение временной метки Time в соответствии с форматом Format |
| sub(s,t,u) | - заменяет в строке u (в случае отсутствия этого аргумента, применяется к текущей записи) первое вхождение регулярного выражения t на строку s |
| system(s) | - строка s интерпретируется, как команда операционной системы и выполняется командным интерпретатором |
| systime() | - возвращает число секунд, прошедших со времени некоторого знаменательного события, с точки зрения OS |
| tolower() | - перевод в нижний регистр |
| toupper() | - перевод в верхний регистр |
| substr(s,m,n) | - Возвращает подстроку строки s, начиная с позиции m, всего n символов. |
Fuction NameOfFunction(a,b,...,z)
{ тело функции }
Имена функций не должны совпадать с встроенными функциями и зарезервированными словами, то есть должны подчиняться соглашению о допустимых идентификаторах в AWK.
Тело функции представляет собой набор AWK -команд. Функция может быть рекурсивной. Количество аргументов за регламентированных в заголовке функции может не совпадать с количеством аргументов при ее вызове, пропущенные аргументы получают значения ""(пусто).
Внешние переменные изменяемые в теле функции не изменяют их значений вне функции. Хотя, если аргументом функции является массив, значения его элементов могут изменятся внутри тела функции.
if ( < условие> ) < предложение>
[else < предложение> ] Предложения цикла:
while ( < условие> ) < предложение>
for (< выражение> ; < условие> ; < выражение> )
<предложение>
Например:
for(i=1; i< =NF; i++) - Аналогично циклу for в языке ''С''
for (i in array) - Цикл по элементам массива. Но, элементы массива доступны в этом случае в случайном порядке.
break - Немедленный выход из цикла.
continue - Переход к выполнению следующего предложения.
next - Немедленный переход к анализу следующей строки.
exit - Выход из программы (на конец input).
# - Комментарий
{ PRINT NR }
/olga/ || /mike/ || /mal/
{PRINT $3}
{PRINT $3 $2}
/olga/ {print > \"folga\"} /mike/ {print > \"fmike\"} /mal/ {print > \"fmal\"}
В данном случае знак "\" поставленный перед кавычками для случая выполения программы непосредственно из командной строки. Если же ваша программа будет храниться в отдельном файле, то того обратного слеша перед кавычками не требуется.