- Язык обработки шаблонов awk
- Чтение awk-скриптов из командной строки
- Позиционные переменные, хранящие данные полей
- Использование нескольких команд
- Чтение скрипта awk из файла
- Выполнение команд до начала обработки данных
- Выполнение команд после окончания обработки данных
- Основные встроенные переменные
- Дополнительные встроенные переменные
- Пользовательские переменные
- Условный оператор if
- Цикл while
- Цикл for
- Массивы
- Форматированный вывод данных
- Встроенные функции
- Математические функции
- Строковые функции
- Функция system
- Пользовательские функции
- Шаблоны
- Как вы пропускаете символы с FIELDWIDTHS в GNU Awk 4.2?
Язык обработки шаблонов awk
Awk — скриптовый язык построчного разбора и обработки входного потока (например, текстового файла) по заданным шаблонам (регулярным выражениям). Часто используется в сценариях командной строки. С помощью языка awk можно выполнять следующие действия:
- Объявлять переменные для хранения данных.
- Использовать арифметические и строковые операторы для работы с данными.
- Использовать управляющие операторы и циклы, что позволяет реализовать сложные алгоритмы.
- Создавать форматированные отчёты.
Вызов awk выглядит так:
Awk рассматривает входной поток как набор записей. Каждая запись делится на поля. По умолчанию разделителем записей является символ новой строки (то есть записи — это строки), разделителем полей — символ пробела или табуляции. Символы-разделители можно явно определить в программе.
- -F fs — позволяет указать символ-разделитель для полей в записи.
- -f file — указывает имя файла, из которого нужно прочесть awk-скрипт.
- -v var=value — позволяет объявить переменную и задать её значение по умолчанию.
- -mf N — задаёт максимальное число полей для обработки в файле данных.
- -mr N — задаёт максимальный размер записи в файле данных.
Чтение awk-скриптов из командной строки
Скрипты awk, которые можно писать прямо в командной строке, оформляются в виде текстов команд, заключённых в фигурные скобки. Кроме того, текст скрипта нужно заключить в одинарные кавычки:
При вызове не указан файл с данными, поэтому awk ожидает поступления данных из STDIN . Чтобы завершить работу awk, нужно передать ему символ конца файла, воспользовавшись сочетанием клавиш CTRL+D .
Позиционные переменные, хранящие данные полей
Одна из основных функций awk заключается в возможности манипулировать данными в текстовых файлах. Делается это путём автоматического назначения переменной каждому элементу в строке. По умолчанию awk назначает следующие переменные каждому полю данных, обнаруженному им в записи:
- $0 — представляет всю строку текста (запись)
- $1 — первое поле в записи (строке)
- $2 — второе поле в записи (строке)
- и так далее
К переменной $n можно обратиться не только с помощью номера 0, 1, 2. Но и использовать переменную или выражение:
Поля выделяются из текста с использованием символа-разделителя. По умолчанию — это пробел или символ табуляции.
Если в качестве разделителя полей используется что-то, отличающееся от пробела или табуляции:
Использование нескольких команд
Awk позволяет обрабатывать данные с использованием многострочных скриптов. Чтобы передать awk многострочную команду, нужно разделить её части точкой с запятой:
Первая команда записывает новое значение в переменную $4 , а вторая выводит на экран всю строку.
Чтение скрипта awk из файла
Awk позволяет хранить скрипты в файлах и ссылаться на них, используя ключ -f . Подготовим файл user-home.awk , в который запишем следующее:
Вызовем awk, указав этот файл в качестве источника команд:
В файле скрипта может содержаться множество команд, при этом каждую из них достаточно записывать с новой строки, ставить после каждой точку с запятой не требуется:
Выполнение команд до начала обработки данных
Иногда нужно выполнить какие-то действия до того, как скрипт начнёт обработку записей из входного потока. Для этого можно воспользоваться ключевым словом BEGIN . Команды, которые следуют за BEGIN , будут исполнены до начала обработки данных.
Выполнение команд после окончания обработки данных
Ключевое слово END позволяет задавать команды, которые надо выполнить после окончания обработки данных:
Напишем скрипт следующего содержания и сохраним его в файле begin-end.awk :
Тут, в блоке BEGIN , создаётся заголовок табличного отчёта. В этом же разделе мы указываем символ-разделитель. После окончания обработки файла, благодаря блоку END , создается подвал отчета. Запустим скрипт:
Основные встроенные переменные
Кроме позиционных переменных $1 , $2 , $3 , которые позволяют извлекать значения полей, есть еще множество других. Вот некоторые из наиболее часто используемых:
- FIELDWIDTHS — разделённый пробелами список чисел, определяющий точную ширину каждого поля данных с учётом разделителей полей.
- FS — переменная, позволяющая задавать символ-разделитель полей.
- RS — переменная, позволяющая задавать символ-разделитель записей.
- OFS — разделитель полей на выводе awk-скрипта.
- ORS — разделитель записей на выводе awk-скрипта.
По умолчанию переменная OFS настроена на использование пробела. Её можно установить так, как нужно для целей вывода данных:
В некоторых случаях, вместо использования разделителя полей, данные в пределах записей расположены в колонках постоянной ширины. В подобных случаях необходимо задать переменную FIELDWIDTHS таким образом, чтобы её содержимое соответствовало особенностям представления данных.
При установленной переменной FIELDWIDTHS awk будет игнорировать переменную FS и находить поля данных в соответствии со сведениями об их ширине, заданными в FIELDWIDTHS .
Переменные RS и ORS задают порядок обработки записей. По умолчанию RS и ORS установлены на символ перевода строки. Это означает, что awk воспринимает каждую новую строку текста как новую запись и выводит каждую запись с новой строки.
Иногда случается так, что поля в потоке данных распределены по нескольким строкам:
Здесь в переменную FS мы записываем символ перевода строки. Это укажет awk на то, что каждая строка в потоке данных является отдельным полем. Кроме того, в переменную RS мы записываем пустую строку. Потому что в файле users.txt блоки данных о разных людях разделены пустой строкой. В результате awk будет считать пустые строки разделителями записей.
Дополнительные встроенные переменные
Помимо встроенных переменных, о которых мы уже говорили, существуют и другие:
- ARGC — количество аргументов командной строки.
- ARGV — массив с аргументами командной строки.
- ARGIND — индекс текущего обрабатываемого файла в массиве ARGV .
- ENVIRON — ассоциативный массив с переменными окружения и их значениями.
- ERRNO — код системной ошибки, которая может возникнуть при чтении или закрытии входных файлов.
- FILENAME — имя входного файла с данными.
- IGNORECASE — если эта переменная установлена в ненулевое значение, при обработке игнорируется регистр символов.
- FNR — номер текущей записи в файле данных.
- NF — общее число полей данных в текущей записи.
- NR — общее число обработанных записей.
Переменные ARGC и ARGV позволяют работать с аргументами командной строки. При этом скрипт, переданный awk, не попадает в массив аргументов ARGV :
Переменная ENVIRON представляет собой ассоциативный массив с переменными среды:
Переменные среды можно использовать и без обращения к ENVIRON :
Переменная NF позволяет обращаться к последнему полю данных в записи, не зная его точной позиции:
Эта переменная содержит числовой индекс последнего поля данных в записи. Обратиться к данному полю можно, поместив перед NF знак $ .
Переменные FNR и NR , хотя и могут показаться похожими, на самом деле различаются. Так, переменная FNR хранит число записей, обработанных в текущем файле. Переменная NR хранит общее число обработанных записей:
Пользовательские переменные
Как и любые другие языки программирования, awk позволяет программисту объявлять переменные. Имена переменных могут включать в себя буквы, цифры, символы подчёркивания. Однако, они не могут начинаться с цифры:
Каждая переменная или поле могут потенциально быть строкой или числом. Awk рассматривает переменную как строковую, пока не возникает необходимость выполнить операции сложения или конкатенации. Если к числу прибавляется строка, то строка автоматически преобразуется в число. Если к строке «прицепляется» число, то число преобразуется в строку.
Условный оператор if
Однострочный вариант оператора:
Если нужно выполнить в блоке if несколько операторов, их нужно заключить в фигурные скобки:
условный оператор if может содержать блок else :
Цикл while
Цикл while позволяет перебирать наборы данных, проверяя условие, которое остановит цикл.
В циклах while можно использовать команды break и continue . Первая позволяет досрочно завершить цикл и приступить к выполнению команд, расположенных после него. Вторая позволяет, не завершая до конца текущую итерацию, перейти к следующей.
Цикл for
Решим задачу расчёта среднего значения числовых полей с использованием цикла for :
Массивы
У awk есть ассоциативные массивы — в качестве индекса можно использовать строку или число. Нет необходимости заранее объявлять размер массива — массив может быть изменен во время выполнения.
Пример использования массива:
Удаление элемента массива:
Форматированный вывод данных
Команда printf позволяет выводить форматированные данные. Она даёт возможность настраивать внешний вид выводимых данных благодаря использованию шаблонов, в которых могут содержаться текстовые данные и спецификаторы форматирования.
Спецификатор форматирования — это специальный символ, который задаёт тип выводимых данных и то, как именно их нужно выводить. Awk использует спецификаторы форматирования как указатели мест вставки данных из переменных, передаваемых printf . Первый спецификатор соответствует первой переменной, второй спецификатор — второй, и так далее.
- %c — воспринимает переданное ему число как код ASCII-символа и выводит этот символ.
- %d — выводит десятичное целое число.
- %i — то же самое, что и d .
- %e — выводит число в экспоненциальной форме.
- %f — выводит число с плавающей запятой.
- %g — выводит число либо в экспоненциальной записи, либо в формате с плавающей запятой, в зависимости от того, как получается короче.
- %o — выводит восьмеричное представление числа.
- %s — выводит текстовую строку.
Встроенные функции
При работе с awk программисту доступны встроенные функции. В частности, это математические и строковые функции, функции для работы со временем.
Математические функции
- cos(x) — косинус x (x выражено в радианах).
- sin(x) — синус x (x выражено в радианах).
- exp(x) — экспоненциальная функция.
- int(x) — возвращает целую часть аргумента.
- log(x) — натуральный логарифм.
- rand() — возвращает случайное число с плавающей запятой в диапазоне от 0 до 1.
- sqrt(x) — квадратный корень из x.
Строковые функции
- length([arg]) — возвращает длину arg ; если arg не указан, то выдает длину текущей строки.
- match(string,pattern) — возвращает позицию вхождения шаблона pattern в строку string ; или 0 , если совпадение не найдено.
- index(string,needle) — возвращает начальную позицию вхождения подстроки needle в строку string ; если needle в string не содержится, возвращает 0 .
- split(string,array[,sep]) — помещает поля строки string в массив array и возвращает число заполненных элементов массива; если указан sep , то при анализе строки он понимается как разделитель.
- sub(replace,pattern[,string]) — заменяет в строке string первое вхождение шаблона pattern на строку replace ; в случае отсутствия аргумента string , применяется к текущей записи.
- gsub(replace,pattern[,string]) — аналогична sub() , но заменяет все вхождения.
- substr(string,start,length) — возвращает подстроку строки string , начиная с позиции start , длиной length символов.
- tolower() — перевод в нижний регистр.
- toupper() — перевод в верхний регистр.
Вот как пользоваться этими функциями:
Функция system
Функция system(«command») выполняет команду command и возвращает состояние выполненной команды.
Пользовательские функции
При необходимости можно создавать собственные функции awk. Для возвращения значения из функции можно использовать оператор return .
Шаблоны
В общем случае программа awk имеет вид:
Каждая запись поочерёдно сравнивается со всеми шаблонами , и каждый раз когда найдено соответствие, выполняется указанное действие . Если шаблон не указан, то действие выполняется для любой записи. Если не указано действие , то запись выводится. Специальные шаблоны BEGIN и END позволяют получить управление перед чтением первой входной строки и после прочтения последней входной строки, соответственно.
В предпоследнем примере $3
/903/ означает, что третье поле содержит строку 903 . В последнем примере $3 !
/903/ все наоборот — третье поле не должно содержать строку 903 .
В шаблонах можно использовать регулярные выражения:
Шаблоны в awk это не просто строка или регулярное выражение. Они могут быть произвольными комбинациями относительных выражений (больше, меньше, равно, не равно, …) и регулярных выражений с использованием ! , || , && и круглых скобок:
/шаблон/
/шаблон/) || (выражение in массив)
В случае использования относительных выражений , , == , != , >= , > происходит сравнение чисел, если оба операнда — числа. В противном случае сравниваются строки.
Источник
Как вы пропускаете символы с FIELDWIDTHS в GNU Awk 4.2?
был выпущен GNU awk 4.2 и содержит множество интересных функций. Один из них:
Синтаксис синтаксического анализа FIELDWIDTHS был расширен, чтобы указать, сколько символов пропустить перед началом поля. Это также позволяет указать «*», поскольку последний символ означает «остальная часть записи». Разделение поля с помощью FIELDWIDTHS теперь правильно устанавливает NF. Документация для FIELDWIDTHS в руководстве была значительно реорганизована и улучшена.
Я тестировал элемент * и отлично работал, чтобы поймать последний блок в $NF :
FIELDWIDTHS был расширен, чтобы пропускать символы перед присвоением значения полю (см. Разделение по контенту).
Я также не могу найти пример в связанном разделе. Таким образом, что именно эта функция выполняет и как она работает?
Документация GNU Awk имеет раздел, где определяется FIELDWIDTHS .
В этом разделе/параграфе также есть некоторые обозначения, которые проливают свет на новую функцию » пропускает символы перед присвоением значения полю«.
Список столбцов, разделенных пробелами, который сообщает gawk , как разделять входные данные с фиксированными границами столбцов. Начиная с версии 4.2, каждый ширина поля может быть необязательно , которому предшествует значение, разделенное двоеточием указав количество символов для пропуска до начала поля. Присвоение значения FIELDWIDTHS отменяет использование FS и FPAT для разделение поля.
Как это происходит на практике:
Скажем, мы хотим пропустить 3 символа перед 1-м полем и 1 символ перед вторым полем.
Итак 3:2 пропускает 123 и устанавливает 45 и 1:2 пропускает 6 и устанавливает 78 .
Источник