Слайд 1
Программирование
вывода текста awk
Программа awk выполняет работу по обработке
файлов, содержащих тексты и числовые данные, и позволяет перераспределять файлы,
выполнять арифметические операции и выборочно восстанавливать строки, используя программные операторы, аналогичные операторам языка Си.
Эту команду можно использовать для сопоставления с образцами или использовать как генератор отчетов для файлов, существующих в системе.
Слайд 2
Внимание. В awk могут быть проблемы с русской буквой
я/Я.
Логика действия:
- сопоставление с шаблоном;
- преобразование текста.
Шаблоны задаются:
- в командной
строке;
- в файле (в этом случае необходимо использовать опцию -f).
Слайд 3
Полная командная строка для awk состоит из четырех частей:
- имени
команды
- [опция -Fсимвол]
[опция -f];
- необязательного оператора-шаблона, если присутствует оператор-действие.
- необязательного оператора-действия, если присутствует
оператор-шаблон;
- имени или имен файлов.
В awk символ # обозначает начало комментария.
Слайд 4
Оператор-шаблон используется для выбора строк из файла,
а оператор-действие
- для работы над этими строками.
Оператор-шаблон должен предшествовать оператору-действию,
который должен быть заключен в фигурные скобки как показано ниже:
awk 'pattern_stateman {action_stateman}' file(s)
Слайд 5
Внимание! Нельзя одновременно опускать и шаблон и действие.
Если не задан
оператор-шаблон, то оператор-действие выполняется над каждой строкой файла или стандартного
ввода.
Если не задан оператор-действие, то строка просто копируется на стандартный вывод.
Если не заданы имена файлов или стоит знак "-", то используется стандартный ввод.
Слайд 6
Если оператор-шаблон и/или оператор действия задаются в командной строке,
то они заключаются в одинарные кавычки с той целью, чтобы
интерпретатор shell их не интерпретировал.
Ввод делится на записи, разделенные специальным символом, по умолчанию это "CR" (возврат каретки).
То есть в awk обработка производится построчно. Разделитель можно поменять, переопределив встроенную переменную RS.
Слайд 7
Записи делятся на поля, разделенные специальным символом (обычно это
“Пробел”).
Его можно переопределить:
- используя встроенную переменную FS;
- указав в
опции –Fсимвол.
Внимание!
Если разделитель “Пробел”, то он не учитывается в начале строки.
Если разделитель “неПробел”, то в начале строки учитываются эти разделители.
Слайд 8
В awk не существует оператора read. awk автоматически получает
каждую запись.
Каждая исходная строка сопоставляется с каждым шаблоном. В случае
успеха выполняется заданные действия.
После сопоставления со всеми шаблонами вводится следующая строка и процесс повторяется.
Строки, которые не удалось сопоставить ни с одним из шаблонов, игнорируются.
Слайд 9
1. Обращение к полям
Как и команда sort, команда awk
ориентирована на работу с полями и реализует простой метод обращения
к полям по имени.
Чтобы обратиться к полю, необходимо перед его номером поставить знак доллара.
Поэтому поле 1 имеет имя $1, поле 2 - $2 и т.д.
Запись $0 обозначает все поля, то есть всю строку.
Слайд 10
Последнее поле обозначается через $NF, где NF - встроенная
переменная, значение которой устанавливается равным числу полей.
Необходимо делать различие
между NF- числом полей и $NF- последним полем строки.
Причем, в команде awk только номера полей начинаются со знака доллара ($), а переменные не имеют такого префикса.
Слайд 11
Например, пусть у нас имеется файл с именем cars.file,
содержащий:
- в первом поле название фирмы,
- во втором -
название марки автомобиля и
- в третьем - его цену.
Тогда применив команду
awk `{print $2 "," $1 "Tab" $3}` cars.file
где "Tab" - знак табуляции (то есть, нажатие на клавишу "Tab").
В этом примере мы сначала выводим на экран марку автомобиля, потом его фирму и только потом цену.
Слайд 12
Причем при выводе на экран между наименованием марки и
наименованием фирмы будет стоять знак запятой, а между фирмой и
ценой - знак табуляции.
ПРИМЕЧАНИЕ!
Если в операторе-шаблоне и операторе-действии содержатся специальные символы, то эти символы должны быть заключены в апострофы.
Открывающая фигурная скобка "{" оператора-действия должна находиться в той же строке, что и связанный с ней шаблон.
Слайд 13
Оператор print “” печатает пустую строку, о оператор print
печатает текущую строку ввода.
Обычно предполагается, что поля в записи разделяются
специальным символом ( обычно это пробел или табуляция), причем количество одновременно разделяющих символов может быть произвольным.
Слайд 14
Этот символ можно переопределить, используя в качестве разделителя любой
одиночный символ.
Один из способов состоит в задании в командной
строке опции -F.
Тогда, к примеру, для печати первого поля в файле, где разделителями является символ двоеточия (:), можно применить команду:
awk -F: '{print $1}' file.my
Слайд 15
Второй способ переопределения разделителя полей - это использование встроенной
переменной FS.
Например, FS = ":";
Обработка пробелов и символов табуляции
здесь особая. По умолчанию и пробелы и символы табуляции служат разделителями, а разделители в начале строки отбрасываются.
Слайд 16
Однако, если в качестве разделителя определен не пробел, то
разделители в начале строки учитываются при определении полей.
В частности,
если используется символ табуляции, то пробелы не являются символами-разделителями и поэтому пробелы в начале строки входят в поле, и каждый символ табуляции определяет поле.
Слайд 17
2. Выполнение команд
из входного файла
Чтобы не набирать каждый раз
команды, как только что в приведенном (ранее) примере, можно поместить
операторы в отдельный файл, сделать файл выполняемым, а затем активизировать этот файл в командной строке awk с помощью опции -f.
Слайд 18
Тогда предыдущий пример можно выполнить так:
cat > file.awk
{print $2 "," $1
"Tab" $3} CTRL-D
# Это ввод строки в файл file.awk
причем операторы-действия вводятся
без апострофов.
awk -f file.awk cars.file
# Запуск программы file.awk
( для того, чтобы сделать файл выполняемым, надо выполнить команду chmod +x file.awk )
Результат выполнения этого примера будет аналогичен предыдущему.
Слайд 19
Итак, выполнение команд из файла необходимо делать в следующей
последовательности:
Поместить команды в файл.
Придать файлу с командами статус выполняемого.
Активизировать этот
файл с опцией -f.
Необходимо помнить, что операторы действия в файле должны быть без апострофов.
Слайд 20
Если в одной строке несколько операторов-действия, то они должны
разделяться символами ";".
Если в в каждой строке располагается только
один оператор, то символ ";" можно опускать.
3. Печать
В команде awk доступна и другая информация. Встроенная переменная NR хранит номер текущей входной записи, то есть номер текущей строки. Поэтому для вставки номера строки перед строкой входного потока достаточно задать значение этой переменной:
awk '{print NR, $0}'
Слайд 21
В операторе print фрагменты, отделяемые запятой, печатаются через символы
разделения полей выходного потока, которые по умолчанию служат пробелами.
Напоминание:
print “”
печатает пустую строку, а
print без аргументов печатает текущую строку ввода.
Слайд 22
Для полного контроля над выходным потоком используется оператор printf,
сходный с аналогичной функцией в языке Си.
Например, в строке
awk
'{printf "%4d %s\n", NR,$0}'
выражение %4d задает поле в четыре цифры для вывода целого NR в десятичном представлении,
а выражение %s - строка символов для вывода $0 и \n - символ перевода строки ( он нужен, так как printf не задает автоматически пробелы или символы перевода строк).
Слайд 23
За каждым оператором print или printf может следовать символ
> и имя файла
(в виде строки в кавычках или
переменной). В этом случае выходной поток будет направлен в этот файл.
Может использоваться и символ >> для дописывания в файл.
Шаблоны
А. Наиболее типичное использование шаблонов в программе awk сводится к задачам простой проверки данных, обычно это поиск строк, удовлетворяющих и неудовлетворяющих некоторому условию.
Слайд 24
Если нет выходного потока, то считается, что данные удовлетворяют
соответствующему критерию.
Например, шаблон для проверки - является ли второе поле
строки пустым - может выглядеть следующим образом:
$2 = "" второе поле пусто
$2 !~/./ второе поле не содержит ни одного символа
length ($2) == 0 длина второго поля равна нулю.
Слайд 25
Символ ~ обозначает соответствие регулярному выражению, а символы !~
- отсутствие соответствия.
Само регулярное выражение заключено в символы дробной черты
(слеши).
Соответствие можно записывать несколькими способами.
Заключение строки в символы наклонной черты.
Например, /Anna/ или /"Anna"/
Слайд 26
Причем необходимо помнить, что это разные шаблоны.
В первом
шаблоне ищется просто слово Anna, а во втором - слово
Anna, заключенное в двойные кавычки.
Поиск будет удачен при нахождении шаблона в любом месте строки ввода. Причем, никакие знаки отмены не используются.
Слайд 27
Операция ~ (соответствие)
Например,
$2 ~ /mm/
или
$2 ~ "mm"
Соответствие с шаблоном
имеет место, когда проверяемое поле содержит подстроку в правой части.
В данном примере отыскивается соотвествие mm в любом месте второго поля.
Слайд 28
Операция !~ (не соответствие)
Например, $2 !~ /mm/
Данный пример соответствует всем
записям ввода, которые не содержат mm где-либо во втором поле.
Примечание:
/Anna/
эквивалентно $0 ~ /Anna/
Слайд 29
В шаблонах можно применять метасимволы, как и в функции
grep:
. - любой символ;
* - любое число повторений предыдущего символа;
^ - начало слова или строки;
$ - конец слова
или строки.
Внимание!
Не путать метасимволы шаблонов и метасимволы командной строки - "*" и "?".
Слайд 30
A. Шаблоны BEGIN и END
Программа awk имеет два специальных шаблона:
BEGIN и END.
Действие, соответствующее BEGIN, выполняется прежде, чем читается первая
входная строка.
Его можно использовать для инициации переменных, печати заголовков или для установки символа разделения полей, присваивая его переменной FS.
Слайд 31
awk 'BEGIN { FS=":"} $2 == "" ' file.my
Здесь в
файле file.my проверяется в каждой строке на пустоту второго поля.
Действия,
указанные в шаблоне END, выполняются после обработки последней входной строки:
awk 'END {print NR}' .....
Здесь печатается число строк входного потока.
Слайд 32
Некоторые версии awk требуют, чтобы шаблон BEGIN был первым
шаблоном программы, а шаблон END = последним
(в Linux не
так).
B. Выражение “Шаблон_1, Шаблон_2” (шаблон диапазонов)
Данный шаблон может использоваться в качестве селектора, то есть указать диапазон строк.
Например, выражение
NR == 10, NR == 20
Слайд 33
задает строки от 10-ой до 20-ой включительно, то есть,
выбираются строки, начиная с первого соответствия первому шаблону, до строки,
соответствующей первому соответствию второму шаблону.
Если второй шаблон не обнаруживается, то все остальные записи считаются соответствующими шаблону.
Слайд 34
Например, в файле file.me находятся строки:
1
2
3
7
9
10
Тогда программа
awk '$1 ==
3,$1 == 10' file.me
выведет строки:
Слайд 35
3
7
9
10
Внимание!
Шаблоны диапазона не могут быть частями сложных шаблонов.
Слайд 36
Если выражение арифметическое, то соответствие будет иметь место в
том случае, если результат будет ненулевым числом.
Если шаблон строка,
то соответствие имеет место, если выражение не является нулевой строкой.
Например, шаблон
$1 <= $2
может вызывать как численное, так и строковое сравнение в зависимости от содержимого полей записи.
Слайд 37
C. Использование арифметических операторов
Достоинством программы awk является ее возможность попутно
с операциями над текстом проводить вычисления над входными потоками данных:
что-нибудь подсчитать, вычислить суммы и средние величины и тому подобное.
Например, попытаемся определить среднюю цену всех автомобилей. Для этого используем:
Слайд 38
- переменную SUM, введенную пользователем;
- переменную команды awk, называемую NR (число
записей или строк, считанных командой awk);
- оператор команды awk, называемый END.
Этот оператор предписывает команде awk ожидать, пока не будут считаны все записи, а затем выполнить следующие действия.
Слайд 39
cat > aw.price
Создание файла aw.price
{SUM = SUM + $3}
Суммирование всех
цен
END
Ожидание считывания всех записей
{print "Aver price: ", SUM/NR} CTRL-D
Вычисление
средней цены
awk -f aw.price cars.file
Выполнение команды awk с опцией -f.
Average price: 3875.34
Выведенный результат
Слайд 40
В этих всех примерах использование опции -f эквивалентно набору
операторов в командной строке для получения результата.
Переменная SUM не является
встроенной, она определяется самим фактом использования.
По умолчанию все переменные инициируются нулем, так что не надо беспокоиться об их инициализации.
Слайд 41
Встроенные переменные awk
FILENAME - имя текущего входного файла,
FS - символ разделения полей (
по умолчанию приняты
символы "Пробел" и "Табуляция"),
RS - символ разделения входных строк (
по умолчанию принят
символ перевода строки),
NF - число полей входной строки,
NR - номер текущей входной записи (FNR),
Слайд 42
OFMT - формат вывода чисел ( по умолчанию принят %6g (См.
printf ),
OFS - строка-разделитель полей в выходном потоке
(по умолчанию принят "Пробел"),
ORS - Строка-разделитель
строк в выходном потоке
(по умолчанию принят символ перевода строки).
Слайд 43
Операции, выполняемые awk
= - присваивание
+ и += - сложение;
- и -= -
вычитание;
* и *= - умножение;
/ и /= - деление;
% и %= - деление
по модулю
^ и ^= - возведение в степень;
II - операция "ИЛИ"
&& - операция "И"
! - отрицание значения выражения
Слайд 44
Операции отношения
> >= <
(префиксные и постфиксными ).
Слайд 45
В awk любое выражение можно использовать с любой операцией.
Преобразование числа в строку и строки в число производится автоматически.
Для
принудительного преобразования в число необходимо добавить ноль:
str = "3"; str += 0;
Получим число 3.
Для принудительного преобразования в строку необходимо добавить пустую строку:
num = 3; num = num "";
Получаем строку "3".
Слайд 46
Встроенные функции awk
cos(Expr) - вычисление косинуса;
sin(Expr) - вычисление синуса;
log(Expr) - вычисление натурального
логарифма;
exp(Expr) - вычисление возведения в степень величины Е;
sqrt(Expr) - вычисление квадратного корня;
int(Expr) -
отбрасывание целой части десятичного числа;
atan2(y,x) - вычисление арктангенса отношения y/x в пределах [-90о,90о];
Слайд 47
rand() - выдает случайное число в пределах (0;1];
srand(Expr) - устанавливает Expr
в новое значеие для rand();
getline () - чтение следующей входной строки.
Возвращает 0 в случае конца файла, в противном случае - 1. Изменяет $0,$1,…,NF,FNR, NR.
getline Var - считывает следующую запись в переменную Var. В этом случае разбиение на поля не происходит, то есть NF остается равной нулю, FNR и NR увеличиваются. Функция getline может применяться с перенаправлением ввода:
Слайд 48
getline < filename
getline Var < filename
Если filename эквивалентно
стандартному вводу, то
происходит ввод с клавиатуры.
index (S1,S2) - положение строки
S2 в строке S1. Возвращает нуль, если строка S2 не входит S1;
length (S) - длина строки S;
Слайд 49
split (S,A,C) - разбиение строки S на массив A[1],A[2]...A[n] по
символу С, который должен находиться в двойных кавычках. Возвращает n.
Если символ C не задан, то
применяется текущее значение переменной FS.
sprintf (Fmt,...) - форматирование в соответствии со спецификацией Fmt;
substr (S,M,N) - выделение подстроки в N символов строки S, начинающейся с индекса M. Если N отсутствует, то тогда до конца строки.
Слайд 50
tolower (Str) - переводит символы строки Str в нижний регистр;
toupper
(Str) - переводит символы строки Str в верхний регистр;
systime - возвращает
текущее время в секундах по Гринвичу (по UTC), начиная отсчет с 1 января 1970 года;
strftime (Fmt,t) - возвращает время t по формату Fmt.
Слайд 51
sub (Re, SubStr, Str) – замещает в строке Str
подстрокой SubStr найденное первое совпадение шаблону (регулярному выражению) Re;
gsub (RegExp,
SubStr, Str) – производит глобальное замещение в строке Str подстрокой SubStr найденные совпадения шаблону Re. Если в этих двух функциях Str опущена, то действие происходит над переменной $0.
Слайд 52
match (Str, Re) - возвращает позицию в строке Str, в
которой располагается подстрока, удовлетворяющая регулярному выражению Re. Она возвращает индекс
начала подстроки, удовлетворяющей шаблону, или 0, если подстрока не существует.
Также эта функция определяет значения переменных RSTART и RLENGTH.
Слайд 53
Примеры:
1. Например, в конвейере
echo 9/29/2014 |
awk '{ split ( $0,date,"/");
print date [3]}‘
строка "9/29/98", которая будет помещена в переменную $0,
разбивается на массив date из трех элементов:
date[1]=9,
date[2]=29,
date[3]=2014. Причем на экран будет выведен значение года - 2014.
Слайд 54
2. Пусть в файле file.txt находятся строки:
Toronto
Paris
Edmonton
Программа на awk
имеет вид:
awk ‘{save = $0
printf “15s\t” $0
gsub(/on/,”ON”,$0)
printf “15s\t” $0
sub(/on/,”ON”,save)
printf “15s\t”
save
}’ file.txt
Слайд 55
В результате получаем:
Toronto TorONto TorONto
Paris Paris Paris
Edmonton EdmONton EdmONtON
Слайд 56
Массивы
Подобно переменным, массивы не нужно описывать.
Размер массива ограничен
только объемом памяти.
В awk индексом массива может быть не
только целое число, но и любое значение.
Название переменных и массивов чувствительно к регистру.
Слайд 57
Пример.
Пусть необходимо подсчитать суммарное значение для каждого имени
игрока.
Anna 400
John 100
Mary 200
Mary 300
John 100
Anna 100
Mary 100
Слайд 58
В результате должно быть:
John 200,
Mary 600,
Anna
500.
Для этого применим программу:
awk ‘END {
for (Name in SUM)
{print Name SUM [Name]}}
{SUM [$1] += $2}’
Слайд 59
Здесь каждое имя $1 служит индексом в массиве SUM.
В конце применена специальная форма цикла for для перебора всех
элементов SUM и их печати.
Синтаксис этого варианта цикла for таков:
for (Var in Array) Operator
Здесь цикл охватывает индексы массива, а не его элементы, устанавливая значение "Var" равным каждому индексу поочередно.
Слайд 60
Однако порядок появления индексов неопределен, поэтому может возникнуть необходимость
в их сортировке.
Например, в приведенном примере выходной поток можно
по конвейеру передать команде sort, чтобы имена шли в порядке убывания значений:
awk '.....' | sort +1 –nr
(сортировка идет по численному полю, начиная со второго в порядке убывания).
Слайд 61
Такой прием очень удобен, чтобы определить, например, частоту появления
слов во входном потоке:
cat > wordfreq.file
awk 'END {
for (word in
Num) print word Num[word]}
{ for ( i=1; ; i++) Num[$i]++}‘ wordfreq.file | sort +1 -nr
Слайд 62
Пример вывода на экран:
the 102
a 51
to
25
The 10
are 7
line 2
print
1
Слайд 63
Здесь в первом цикле for выбирается каждое слово из
входной строки и заполняется массив Num, индексируемый словами.
Причем нельзя
путать $i, обозначающее i-е поле входной строки, с переменными языка shell.
После того, как файл будет прочитан, во втором цикле for печатается слово и частота его появления.
Слайд 64
Для удаления некоторого элемента из массива применяется встроенная функция
delete.
Например,
delete name[1]
удаляет первый элемент массива name из
памяти компьютера.