
LabLinux / laba2_m3_iems_iems_ktni_niy16
.pdfМодуль 3. Лабораторная работа №2 Программирование в среде AWK
Цель работы: на основе ранее полученных навыков работы с командным интерпретатором BASH овладеть начальными навыками программирования на языке создания фильтров AWK.
Теоретические сведения
Программируя в Shell, иногда не хватает имеющихся средств стандартных команд и средств перенаправления данных для создания гибких условий поиска и обработки полученных результатов. Требуются принципиально новые условия создания запросов и новые средства обработки информации. Нам уже известно, что стандартными фильтрами для создания и обработки запросов являются такие команды как cat, sort, find, grep, egrep, fgrep, cmp, diff и некоторые другие. Однако их возможности ограничены либо работой самой команды, либо работой в составе опций. Что же делать, если требуется создать более гибкие условия поиска и обработки информации в Linux? На этот счет можно воспользоваться встроенной в Linux программной средой AWK.
При форматировании отчетов и извлечении информации из больших текстовых файлов неоценимую помощь нам оказывает утилита awk, снабженная мощными средствами обработки текста. Основная задача утилиты awk состоит в просмотре текстового файла или строки с целью нахождения в них информации, соответствующей заданному критерию отбора. Утилита имеет собственный язык программирования, поэтому ее можно назвать программируемым фильтром, настроенным на выполнение конкретной задачи. Фактически awk выполняет две функции. С одной стороны, это фильтр, который можно вызвать из командной строки так же, как и любой другой фильтр. С другой стороны, awk — это среда программирования, с помощью которой можно создавать другие фильтры.
Фильтры, создаваемые с применением языка программирования awk, могут использоваться в среде любого интерпретатора Linux, в том числе shell, BASH и TCSH. Их задача заключается в считывании информации из источника данных, например текстового файла или стандартного потока ввода, изменении и анализе считанного, сохранении выходных данных. Результатом работы awk, как правило, являются отредактированные входные данные. Вы можете дать указание awk считывать данные из файла, сортировать их в алфавитном порядке либо по номерам строк и направлять строки текста в выходной поток, как это делает фильтр sort, либо, подобно фильтру wc, считывать информацию из файла, подсчитывать количество слов и строк в тексте, а затем отображать полученные результаты. С помощью awk Вы можете выполнить поиск в файле информации, соответствующей заданному шаблону, после чего вывести найденные строки, то есть выполнять функции, присущие утилите фильтрации grep.
Язык программирования gawk позволяет пользователю не только разрабатывать собственные фильтры, но и создавать команды Linux. С его помощью можно отображать строки вводимого текстового файла на экране (cat), выполнять поиск информации в файлах в соответствии с заданными шаблонами (grep) и даже подсчитывать, сколько раз встречается определенное слово в текстовом файле
(wc). В каждом из указанных случаев пользователь может добавить собственные функции, обеспечивающие фильтрацию, например, задать отображение лишь части каждой строки, выполнение поиска по шаблону в указанном поле или подсчет слов, набранных только прописными буквами. Подобная гибкость дает возможность использовать awk для создания отчетов, поиска заданных текстовых фрагментов и выполнения вычислений на основе вводимых данных.
Утилиту awk можно вызвать непосредственно из командной строки или из shell-сценария с помощью ключевого слова awk. Такой сценарий часто рассматривают как новый фильтр. Фактически с помощью awk вы можете определять собственные фильтры. В этом случае реализуются обе функции утилиты — и как фильтра, и как среды программирования.
Утилита awk обладает гибким и сложным языком программирования и поддерживает команды, которые позволяют анализировать текст и выполнять расчеты. Можно также объявлять переменные и использовать их для управления процессом обработки строк. Многие операторы взяты из языка программирования С и имеют такой же синтаксис.
Команда awk принимает в качестве аргументов инструкцию фильтра и список имен файлов. Инструкция заключается в одинарные кавычки и рассматривается как один аргумент. Она состоит из двух сегментов: шаблона и кода, задающего действие. Команды, определяющие действие, заключаются в фигурные скобки. Шаблонная часть уточняет, когда следует выполнять действие либо по отношению к каким входным данным оно должно производиться. В утилите awk имеется целый набор операций для построения сложных условий. Поиск по шаблону можно рассматривать как условие поиска записей. Вместо простого сопоставления с шаблоном, как в случае с grep, пользователь задает условие. Записи, которые удовлетворяют этому условию, выбираются, и к ним применяются действия, указанные в соответствующем сегменте. Синтаксис инструкции таков: шаблон {действие}
Утилита awk получает данные либо из файлов, либо со стандартного устройства ввода. Имена файлов можно указать в командной строке после инструкции. Если таковые не указаны, то входные данные берутся со стандартного устройства ввода. Вызов этой утилиты состоит из ключевого слова awk, инструкции и имен файлов. Как и в фильтре sed, инструкция помещается в одинарные кавычки, чтобы shell ее не интерпретировал. Поскольку условие и действие рассматриваются утилитой gawk как единый аргумент, их нужно заключить в одну пару кавычек. Синтаксис команды awk показан в следующем примере.
$ gawk 'шаблон {действие}' имена_файлов
Шаблон в инструкции можно рассматривать как прототип строки в файле. Указанное действие выполняется над этой строкой. В следующих двух примерах на экран выводятся все строки, содержащие слово Maxim. В сегменте «шаблон» необходимо задать поиск по шаблону, для чего шаблон выделяется символами косой черты. Выбираться будут все записи с этим шаблоном. Сегмент «действие» в первом примере содержит команду print, которая направляет строку на стандартное устройство вывода.
Исходное содержание текстового файла «names»
Anton Andrey 15.75 Maxim
Roman Denis 3.50 Nikolay
Ilnur Pavel 10.25 Anatoliy Fedor Michail 2.50 Vladimir
$ gawk '/Maxim/{print}'names
Anton Andrey 15.75 Maxim
Во втором примере сегмента «действие» нет, поэтому применяется действие, заданное по умолчанию, то есть команда print.
$ gawk '/Maxim/'names
Anton Andrey 15.75 Maxim
Поиск по шаблону и специальные символы
Утилита awk может выбирать строки, используя шаблон, который содержит специальные символы. Сам шаблон обозначается двумя косыми и помещается в сегменте шаблона инструкции awk.
/шаблон/ {действие}
Поиск по шаблону осуществляется во всех строках файла. Указанное действие выполняется по отношению к строке, в которой обнаруживается шаблон. В этом случае выполняемая awk работа очень похожа на редактирование. Как и в sed, строка рассматривается в качестве строки текста, а поиск шаблона осуществляется во всей строке. В следующем примере awk ищет строку с шаблоном Fedor и, найдя, выводит ее на экран.
$ gawk '/Fedor/{print}' names
Fedor Michail 2.50 Vladimir
В awk можно использовать те же специальные символы, что и в регулярных выражениях, в фильтре sed и редакторе Ed. В первом из приведенных ниже примеров поиск шаблона выполняется в начале строки, обозначенном специальным символом ^. Во втором примере поиск шаблона производится в конце строки, который обозначен специальным символом $.
$ awk '/^Anton/{print}' names
Anton Andrey 15.75 Maxim
$ awk '/Anatoliy$/{print}' names
Ilnur Pavel 10.25 Anatoliy
Как и в утилитах Ed и sed, в awk с помощью специальных символов можно задавать разновидности шаблона: точка обозначает любой символ, звездочка — несколько экземпляров шаблона, а квадратные скобки — набор символов. В показанном ниже примере точка используется для поиска шаблона, в котором за одним произвольным символом следуют символы «ur».
$ awk '/.ur/{print}' names
Ilnur Pavel 10.25 Anatoliy
В следующем примере используются квадратные скобки и звездочка, то есть задается последовательность чисел. Набор возможных чисел определен диапазоном цифр в квадратных скобках, [0—9]. Звездочка обозначает любое количество экземпляров чисел. Заканчивается шаблон последовательностью символов .50. Совпадением считается любое число, которое заканчивается указанными символами .50. Обратите внимание: перед точкой стоит обратная косая черта, благодаря чему программа рассматривает ее именно как точку, а не как специальный символ.
$ awk '/[0-9]*\.50/ {print}' names
Roman Denis 3.50 Nikolay Fedor Michail 2.50 Vladimir
Кроме этого, в awk используются специальные символы расширенного набора: +, ? и |. Символы + и ? — это варианты специального символа *. Символ + обозначает один или несколько экземпляров какого-либо символа, а ? — ни одного или один экземпляр символа. Символ | позволяет задать другие искомые шаблоны. В следующем примере пользователь ищет строку, содержащую либо шаблон
Maxim, либо шаблон Anton.
$ awk '/Maxim|Anton/ {print}'names
Anton Andrey 15.75 Maxim
Переменные, операторы и массивы
В awk поддерживаются определения переменных различных типов, массивов и стандартных арифметических операторов и операторов присваивания, которые существуют в большинстве языков программирования. В состав awk включены также условные операторы.
Утилита awk позволяет определять переменные. Существует три типа переменных: переменные для обозначения полей, специальные переменные и пользовательские переменные. Переменные для обозначения полей и специальные переменные утилита определяет автоматически. Пользователь может определять собственные переменные. Кроме того, можно определять арифметические и строковые константы. Арифметические константы состоят из цифр, а строковые — из любых символов, заключенных в двойные кавычки.
Поле — это любой набор символов, ограниченный разделителем полей. По умолчанию в качестве разделителя используется пробел или знак табуляции. Как и другие фильтры, awk нумерует поля, начиная с 1. Утилита определяет переменную для каждого поля файла. Имя переменной, обозначающей поле, состоит из знака $ и номера поля. Так, имя $2 указывает на второе поле. Переменная $0 — это специальная переменная, содержащая всю строку.
В следующем примере выводятся второе и четвертое поля файла «names», именуемые $2 и $4.
$ awk '{print $2, $ 4 } ' names
Andrey Maxim
Denis Nikolay
Pavel Anatoliy
Michail Vladimir
Переменной можно присвоить значение с помощью операции присваивания =. Значение может быть содержимым переменной (скажем, переменной, обозначающей поле), специальной переменной или пользовательской переменной. Оно может быть и константой. В примере пользователь присваивает переменной myfield значение второго поля.
$ awk ‘{myfield = $2; print myfield}' names
Maxim
Nikolay
Anatoliy
Vladimir
По умолчанию awk разделяет поля символами пробела или табуляции. Однако можно определить собственные разделители, которые нужно явно задать посредством опции -F. Фактически при использовании этой опции устанавливается специальная переменная FS, выступающая в роли разделителя поля. В качестве разделителя можно указать любой символ.
Арифметические операторы и операторы присваивания
Язык awk поддерживает полный набор арифметических операторов, обеспечивающих выполнение операций сложения, вычитания, умножения, деления, а также деления с остатком. Арифметические операторы аналогичны операторам языка программирования С.
В awk существует возможность выполнять арифметические вычисления над значениями, заданными числовыми шаблонами. Числовой шаблон представляет собой последовательность цифр. Примерами шаблона могут служить арифметическая константа или поле, содержимым которого являются числа. Арифметические константы, переменные полей, а также определяемые пользователем переменные, значения которых представляют числовые шаблоны, могут использоваться в качестве операндов арифметических операций. Существует также ряд встроенных числовых переменных awk, например NR, определяющая номер текущей записи, и NF, задающая количество полей в текущей записи. Такие переменные могут применяться и в качестве арифметических операндов.
Арифметические операции обычно вводятся в сегменте действия или шаблона инструкции awk. В следующем примере выводятся все четные строки. Знак процента (%) представляет собой оператор деления по модулю, результатом выполнения которого является остаток от деления на число. Если остаток от деления номера строки на 2 равен нулю, значит, номер строки четный.
$ awk '(NR % 2) = = 0 {print NR, $0}'names
2 Roman Denis 3.50 Nikolay
4 Fedor Michail 2.50 Vladimir
Арифметические операторы и переменные позволяют выполнять вычисления над значениями полей таблиц, хранящихся в базе данных. Например, сумму значений в заданном столбце можно вычислить так, как это делается в электронной таблице. Рассмотрим пример, в котором суммируются значения третьего столбца таблицы из файла «names». Суммируемое значение присваивается переменной tot, определенной пользователем. Для вывода на печать итогового
значения tot используется специальный шаблон END. При этом считается, что значение переменной tot при инициализации автоматически устанавливается равным 0.
$ awk '{print; tot = tot + $3} END {print "Total=",tot}' names
Anton Andrey 15.75 Maxim
Roman Denis 3.50 Nikolay
Ilnur Pavel 10.25 Anatoliy Fedor Michail 2.50 Vladimir Total= 32
Наряду со стандартными арифметическими операторами в awk применяются составные арифметические операторы присваивания. Составные операторы представляют собой комбинацию арифметических операторов и операторов присваивания. Они используются для сокращенной записи операции присваивания, когда в переменной сохраняется результат вычисления выражения, в котором применяется эта же переменная. Например, операция tot = tot + 1 может записываться с помощью составного арифметического оператора += в виде tot +=
1.В данном случае в арифметическом выражении переменную tot указывать не требуется, поскольку само применение составного арифметического оператора += уже предполагает ее наличие. Аналогичным образом, и оператор i = i * 2 может быть записан с применением составного арифметического оператора *= в виде i *=
2.Результат выполнения приведенной ниже команды такой же, как и в предыдущем примере:
$ gawk '{print; tot += $3} END {print "Total=", tot)’ names
Anton Andrey 15.75 Maxim
Roman Denis 3.50 Nikolay
Ilnur Pavel 10.25 Anatoliy Fedor Michail 2.50 Vladimir Total= 32
Массивы и ассоциативные массивы
Вawk к элементу массива обращаются, как и в обычных языках программирования — с помощью индекса, заключенного в скобки и помещенного после имени массива. Массив, подобно переменным, определяется после первого использования индекса. Однако в среде awk, в отличие от некоторых языков программирования, объявлять массив и задавать его границы не требуется. В awk массивы являются динамическими и их размерность увеличивается по мере добавления новых элементов.
Вследующем примере объявляется массив «titles», каждому элементу которого присваивается значение первого поля в строке. Этот массив может содержать произвольное количество элементов (в данном случае оно равно количеству строк). В качестве индекса массива используется переменная «num», значение которой увеличивается на единицу после каждого обращения к элементу массива. По окончании вычисления на печать выводится последний элемент массива.
$ awk ' {titles [num] - $1; num++} END {print titles [num -1]}' names
Vladimir
Предположим, требуется присвоить значение каждому полю отдельной записи массива. Это можно реализовать с помощью обычных операторов присваивания, задавая нужное значение для каждого поля. Существует и более короткий путь решения задачи — использование функции split, которая разделяет строку символов на сегменты и помещает полученные сегменты в массив. Аргументами функции split являются входная строка символов, результирующий массив и символ-разделитель. Символ-разделитель представляет собой строку. Если символ-разделитель не указан, в качестве разделителя по умолчанию применяется символ пробела или табуляции.
Функцию split можно использовать и для обработки строковых значений. Например, функция split ("9-10-92" ,date,"-") присваивает значение 9 элементу массива date[l], значение 10 — элементу date[2], а значение 92 — элементу date[3]. В следующем примере значение каждого поля строки присваивается элементу массива myrec. Выбор присваиваемой строки осуществляется с помощью шаблона /Anton/. Вывод полей производится в обратном порядке. В awk можно также определять ассоциативные массивы. В массивах такого типа в качестве индекса используются строковые значения.
$ awk '/Anton/ (split($0, myrec); print myrec[4], myrec[3], myrec[2], myrec[1]}' names
Anton Andrey 15.75 Maxim
Использование шаблона в качестве условия
Винструкции awk шаблоном может служить условная или составная управляющая конструкция либо регулярное выражение. В языках программирования условные управляющие конструкции содержат выражения, принимающие истинные либо ложные значения. Если результат проверки условия является истинным, выполняются операторы управляющей конструкции. Шаблон утилиты awk также может выступать в качестве условия проверки. Если результат сравнения с шаблоном положителен, должно производиться действие, заданное в инструкции awk. В этом смысле шаблон может рассматриваться как проверяемое условие, определяющее, какие действия должны выполняться.
Вязыках программирования условные управляющие конструкции могут быть достаточно сложными, включать по нескольку логических операторов и операторов сравнения, а также арифметические выражения и даже вызовы функций. Подобно языкам программирования, шаблоны awk также могут быть достаточно сложными и содержать подшаблоны, использующие логические и арифметические операторы, а также операторы сравнения. В этом смысле шаблон можно рассматривать как синоним термина «выражение». Однако тогда как используемые в языках программирования операнды представляют собой числа или строки, в шаблоне awk операнды рассматриваются как образцы, с которыми производится сравнение. В awk в ходе выполнения операции сравнения с шаблоном рассматривается некоторое значения. Логические операции включают подвыражения, которые и выполняют сравнение с шаблоном. Фактически на подвыражения ссылаются как на «шаблоны», а сложные логические операции будут именоваться «составными шаблонами».
Равенство и операторы сравнения
Простые тестируемые выражения можно сформировать с помощью оператором проверки на равенство значений, переменных полей и констант. Операторы проверки на равенство аналогичны подобным операторам языка программирования С. В awk такой оператор обозначается двумя знаками равенства (==). Этим он отличается от подобного оператора в других языках программирования. Одиночный знак равенства обозначает оператор присваивания =. Поэтому нужно быть внимательным, используя эти операторы. Оператор проверки на неравенство обозначается восклицательным знаком, за которым следует знак равенства, !=. Применение указанных операторов демонстрирует следующий пример. Здесь на печать выводятся только те строки, в последних полях которых находится строка «Anatoliy».
$ awk '$4 == "Anatoliy" {print}' names
Ilnur Pavel 10.25 Anatoliy
Для формирования логических выражений, выполняющих проверку условий, можно применять также операторы сравнения. Утилита awk использует те же операторы сравнения, что и другие языки программирования: >, <, >= и <= . Операторы сравнения awk позволяют сопоставлять даже строковые значения. Сравнение производится в соответствии с алфавитом. В следующем примере пользователь просматривает рейтинг студентов, средний балл которых не превышает 10.00. Обратите внимание, что в качестве одного из операндов применяется числовая константа.
$ awk '$3 > 10.00 {print}' names
Anton Andrey 15.75 Maxim Ilnur Pavel 10.25 Anatoliy
Логические операции
В awk существует множество логических операторов, которые могут применяться для проверки некоторых условий. Логический оператор AND обозначается двойным амперсандом &&, оператор OR — двумя вертикальными линиями ||, а оператор NOT — восклицательным знаком !. При работе с логическими операторами обычно применяются скобки. В следующем примере выполняется проверка значения первого поля записи, содержащей шаблон «Anton», и значения третьего поля с числом более 10.00.
$ awk '($1 == "Anton") && ($3 > 10.00) {Print)'names
Anton Andrey 15.75 Maxim
В следующем примере пользователь формирует список строк файла с именами
Anton и Fedor.
$ awk '($1 = "Anton") || ($1 == "Fedor") {print}' names
Anton Andrey 15.75 Maxim
Fedor Michail 2.50 Vladimir
Поиск по шаблону
Специальные символы ~ и !~ применяются для выполнения поиска по шаблону в полях текущей записи. Вместо того чтобы посредством операции = сравнивать все поля с шаблоном, можно с помощью операции ~ проверить, присутствует ли конкретный шаблон в поле. При таком поиске в полях правый операнд — это шаблон, а левый — поле, в котором его нужно найти. В следующем примере в первом поле выполняется поиск шаблона «on»:
$ awk '($1 ~ /on/) (print)' names
Anton Andrey 15.75 Maxim
А ниже представлен пример, где производится выборка всех записей, в первом поле которых шаблон «on» отсутствует.
$ awk ($l !~ /on/) {print}' names
Roman Denis 3.50 Nikolay
Ilnur Pavel 10.25 Anatoliy Fedor Michail 2.50 Vladimir
Контрольные вопросы
1)Назначение фильтра AWK?
2)Проведение арифметических операций. Назовите команды. Как ими пользоваться?
3)Назначение массивов и работа с массивами.
4)Назначение логических операций.
5)Осуществление поиска по шаблону.
6)Назначение файлов инструкций.
7)Назначение операторов сравнения. Приведите примеры.