Изучаем команды linux: awk

Как разделить поля

После прочтения записи одна из предопределенных переменных FS, FIELDWIDTHS или FPAT будет использоваться для разделения поля. После того, как разделение завершено, введите основной сегмент кода (таким образом, установка FS в main не влияет на запись, которая была прочитана на этот раз, но повлияет на следующее чтение).

Метод разделения поля (1): FS или -F

или: Разделитель полей

  • Когда FS — один символ, символ является разделителем поля
  • Когда FS состоит из нескольких символов, шаблон регулярного выражения используется в качестве разделителя полей
  • Специальный также стандартная ситуация FS,Когда FS — это один пробел, в качестве разделителей полей будут использоваться непрерывные пробелы (пробелы, табуляции, разрывы строк).
  • Специально, когда в ФС есть пустая строка «», каждый символ будет разделен, то есть каждый символ используется в качестве поля
  • Установите предопределенную переменную IGNORECASE в ненулевое значение. Когда регулярное сопоставление означает, что игнорируется регистр (влияет только на регистр, поэтому FS не действует, когда это одно слово)
  • Если разделитель, указанный в FS, не может быть найден в записи (например, установите FS в «\ n»), вся запись используется в качестве поля, то естьс участиемравный

Метод разделения поля (2): ОБЛАСТИ ПОЛЯ

Укажите предопределенную переменную FIELDWIDTHS, чтобы разделить поле по ширине символа, что является расширенной функцией gawk. Очень полезно при работе с пропущенными полями.

использование:

Пример 1:

Пример 2. Обработка данных, отсутствующих в определенных полях.

Если сегментация полей выполняется в соответствии с обычной FS, трудно обрабатывать строки с пропущенными полями и строки без пропущенных полей равномерно, но очень удобно использовать FIELDWIDTHS.

Предположим, текстовое содержимое файла a.txt выглядит следующим образом:

Поскольку некоторые поля электронной почты являются пустыми полями, неудобно напрямую разделять поля с помощью FS. FIELDWIDTHS могут быть использованы.

Метод разделения поля (3): FPAT

FS должен указать разделитель полей для получения части, отличной от разделителя, в качестве поля.

FPAT должен получить соответствующую часть символа в виде поля. Это расширенная функция, предоставляемая gawk.

FPAT сопоставляет запись глобально в соответствии с заданной регулярностью, а затем составляет все части, которые успешно совпадают, Не изменится。

  • После установки FS или FPAT эта переменная будет недействительной

FPAT часто используется в сценариях, где в поле включен разделитель полей. Например, строка данных в файле CSV выглядит следующим образом:

Запятая разделяет каждое поле, но двойные кавычки окружают поле целиком, даже если в нем есть запятая.

В настоящее время удобнее использовать FPAT для разделения полей, чем использовать FS.

Наконец, функция patsplit () такая же, как FPAT.

Отчет в РАО из файла

cat "./отчет 3 кв 2015.txt" |\
iconv -c -f cp1251 -t utf-8 |\
grep -v "^---" | grep -v "^Title  " |\
sed "s/^.\{37\}/&===/" | sed "s/^.\{56\}/&===/" | sed "s/^.\{67\}/&===/" |\
sed "s/^.\{78\}/&===/" | sed "s/^.\{105\}/&===/" | sed "s/^.\{143\}/&===/" |\
sed "s/\t/ /g" | sed "s/\r/ /g" | sed "s/  */ /g" |\
awk 'BEGIN{FS=" ==="}{split($3, a, ":"); if ($6!="" && $5!="") print $1"\t"$5"\t"$5"\t"$3"\t"$4*1"\t"(a*60+a)*$4"\tпесня\t"$2"\tСобственная фонотека"}' \
> ./rao_отчет_3_кв_2015.cvs

исходный файл (./отчет 3 кв 2015.txt) вида таблицы:

Title                                Artist          Length  Times   Composers               Publisher       Record Label
---------------------------------------------------------------------------------------------------------------------------------
Nothing Like The Rain                2 UNLIMITED     04:39   0015    A.D.Dels, J.P.De Coster ZYX Music                           
Here Without You                     3 DOORS DOWN    03:53   0011    Arnold/Harrell/Henderso UNIVERSAL                           

Тут интересно решение по разбиению таблицы на ячейки с помощью:

sed "s/^.\{37\}/&===/"

Тут 37 это ширина первой ячейки в символах в конец добавляем === для отделения ячейки, 56 это конец второй ячейки с учетом добавленного разделителя «===»

Еще интересный момент в awk:

split($3, a, ":");

Тут переменная $3 в которой находится время композиции в виде 04:39 и получаем массив a=04 и a=39

Заменяем последовательность пробелов одним пробелом:

sed "s/  */ /g"

Встроенные переменные и расширенный формат awk

Awk использует некоторые встроенные переменные, чтобы определять фрагменты информации при обработке текста.

Список встроенных переменных awk:

  • FILENAME: ссылается на текущий входной файл.
  • FNR: Ссылается на номер текущей записи относительно текущего вводного файла. Например, если в данный момент открыто два вводных файла, команда выведет номер записи каждого из них.
  • FS: текущий разделитель полей, который используется для обозначения каждого поля в записи. По умолчанию установлен пробел.
  • NF: количество полей в текущей записию
  • NR: номер текущей записи.
  • OFS: разделитель полей для выводимых данных. По умолчанию установлен пробел.
  • ORS: разделитель записей для выводимых данных. По умолчанию установлен символ новой строки.
  • RS: разделитель записей, отделяющий записи во входном файле. По умолчанию это символ новой строки.

Значения этих переменных можно менять в соответствии с потребностями файлов. Обычно это делается во время инициализации обработки awk.

В целом, синтаксис awk немного более сложный, чем кажется сначала. Кроме того, он содержит дополнительные блоки BEGIN и END, которые могут содержать команды, которые нужно выполнить перед или после обработки файла соответственно.

Расширенный синтаксис выглядит примерно так:

Ключевые слова BEGIN и END, на самом деле, просто конкретные совокупности условий, так же, как и параметры поиска. Они совпадают до и после обработки документа.

Это значит, что некоторые переменные блока BEGIN можно изменить. К примеру, файл /etc/passwd разделён с помощью исмволов двоеточия (:), а не пробелов. Чтобы вывести первый столбец этого файла, можно использовать:

Блоки BEGIN и END можно использовать, чтобы получить простую информацию о выведенных полях:

Как видите, воспользовавшись некоторыми функциями awk, можно достаточно гибко отформатировать некоторые параметры.

Оба блока расширения – необязательны. По сути, основные действия тоже необязательны, если другая часть действий уже указана. К примеру, с awk можно работать так:

Как работает awk?

На самом деле awk – это изначально язык программирования, предназначенный для обработки текста/данных. Поскольку, как уже отмечалось, в Linux-системах основной средой для взаимодействия между пользователем и машиной является текст, то обработка достаточно больших его объёмов вручную способна была парализовать на некоторое время процесс выполнения основной работы. Требовался инструмент для обеспечения автоматической обработки данных и позволяющий использовать эту возможность «на лету», т. е. прямо при работе в командной оболочке. Лучшим средством для достижения этой цели является использование специализированного языка программирования и регулярных выражений, которое реализовано в виде одноимённой утилиты — команды awk.

Справедливо заметить, что awk – это прежде всего Си-подобный язык программирования, но для удобства понимания, под awk принято понимать утилиту или команду. Разработчиками языка AWK являются Alfred V. Aho, Peter J. Weinberger и Brian W. Kernighan, по сокращённым инициалам которых язык и получил своё название. Создан язык в 1977 году. Кстати, на основе AWK когда-то был создан язык Perl, который и по сей день является одним из самых мощных языков для высокопроизводительной обработки данных.

В качестве исходных данных awk принимает на вход строку и после её обработки в зависимости от конкретных опций выдаёт результат. Исходные данные могут поступать из файла или из вывода другой команды/программы. Самым распространённым случаем использования awk является выборка определённых столбцов из результата вывода других команд, например:

$ ll | awk '{print $9}'

В результате вывод будет примерно таким:

Следует напомнить, что по-умолчанию вывод команды ll выглядит следующим образом:

Как видно, команда awk помогла вывести только отдельный столбец из общего вывода ll – с именами каталогов и файлов.

Конечно, для решения подобных задач существует утилита grep, но awk гораздо быстрее и производительнее для обработки больших и сложных массивов данных.

Использование awk в Linux

Простейшая и часто востребованная задача – выборка полей из стандартного вывода. Вы не найдете более подходящего инструмента для решения этой задачи, чем awk. По умолчанию awk разделяет поля пробелами. Если вы хотите напечатать первое поле, вам нужно просто использовать функцию print и передать ей параметр $1, если функция одна, то скобки можно опустить:

echo ‘one two three four’ | awk ‘{print $1}’

Да, использование фигурных скобок немного непривычно, но это только в первое время. Вы уже догадались как напечатать второе, третье, четвертое, или другие поля? Правильно это $2, $3, $4 соответственно.

echo ‘one two three four’ | awk ‘{print $3}’

Иногда необходимо представить данные в определенном формате, например, выбрать несколько слов. AWK легко справляется с группировкой нескольких полей и даже позволяет включать статические данные:

echo ‘one two three four’ | awk ‘{print $3,$1}’

echo ‘one two three four’ | awk ‘{print “foo:”,$3,”| bar:”,$1}’

Если поля разделены не пробелами, а другим разделителем, просто укажите в параметре -F нужный разделитель в кавычках, например “:” :

echo ‘one mississippi:two mississippi:three mississippi:four mississippi’ | awk -F”:” ‘{print $4}’

Но разделитель не обязательно заключать в кавычки. Следующий вывод аналогичен предыдущему:

echo ‘one mississippi:two mississippi:three mississippi:four mississippi’ | awk -F: ‘{print $4}’

Иногда нужно обработать данные с неизвестным количеством полей. Если вам нужно выбрать последнее поле можно воспользоваться переменной $NF. Вот так вы можете вывести последнее поле:

echo ‘one two three four’ | awk ‘{print $NF}’

Также вы можете использовать переменную $NF для получения предпоследнего поля:

echo ‘one two three four’ | awk ‘{print $(NF-1)}’

Или поля с середины:

echo ‘one two three four’ | awk ‘{print $((NF/2)+1)}’

echo ‘one two three four five’ | awk ‘{print $((NF/2)+1)}’

Все это можно сделать с помощью таких утилит как sed, cut и grep но это будет намного сложнее.

Как я рассказывал выше, awk обрабатывает одну строку за раз, вот этому подтверждение:

echo -e ‘one 1n two 2’ | awk ‘{print $1}’

А вот пример фильтрации с помощью условия, выведем только строку, в которой содержится текст one:

echo -e ‘one 1n two 2’ | awk ‘/one/ {print $1}’

А вот пример использования операций с переменными:

echo -e ‘one 1n two 2’ | awk ‘{sum+=$2} END {print sum}’

Это означает что мы должны выполнять следующий блок кода для каждой строки. Это можно использовать, например, для подсчета количества переданных данных по запросам из журнала веб-сервера.

Представьте себе, у нас есть журнал доступа, который выглядит так:

Мы можем подсчитать, что количество переданных байт, это десятое поле. Дальше идёт User-Agent пользователя и он нам не интересен:

cat /var/log/apache2/access.log | awk ‘{print $10}’

Вот так можно подсчитать количество байт:

< requests.log awk ‘{totalBytes+=$NF} END {print totalBytes}’

Это только несколько примеров показывающих использование awk в Linux , освоив awk один раз в получите очень мощный и полезный инструмент на всю жизнь.

Часть первая: Так что такое AWK?

Awk, главным образом, это потоковый редактор вроде sed. Вы можете передавать по трубе текст в эту программу, и она может манипулировать им построчно. Программа также может читать из файла. Ещё awk – это язык программирования. Это в основном означает, что awk может делать всё, что может sed, а также ещё многое другое.

В отличие от sed, awk может помнить контекст, делать сравнения и многие другие вещи, которые могут делать другие языки программирования. Например, она не ограничена единичной строкой. При надлежащей сноровке, она может ОБЪЕДИНЯТЬ множество строк.

Самая простая форма awk выглядит так:

awk '{ здесь_какое-то_действие }'

«Здесь_какое-то_действие» может быть просто выражением для печати результата или чем-то намного более сложным. Синтаксис похож на язык программирования ‘C’. Простой пример:

awk '{print $1,$3}'

означает напечатать первый и третий столбец, где под столбцами понимаются «вещи, разделённые белым пробелом». Белый пробел = табуляция или пробел.

Живой пример:

echo '1 2 3 4' | awk '{print $1,$3}'

1 3

Условные операторы и поиск по полям

В одном из приведенных выше примеров в файле /etc/fstab была найдена последовательность «UUID». Это было просто, так как нужно было найти строку, содержащую эту последовательность в начале.

Но что, если нужно найти последовательность, расположенную в начале поля?

Можно создать тестовый файл favorite_food.txt, содержащий пронумерованный список любимых продуктов группы друзей.

Чтобы вывести все слова, начинающиеся с «sa», используйте:

В выведенном результате показаны не только слова, начинающиеся с последовательности «sa». Это касается слова «wasabi», которое содержит нужную последовательность в середине; кроме того, слово «sandy» также не совсем соответствует шаблону, так как находится в другом столбце. Нужно вывести только слова, которые начинаются с «sa» во втором столбце.

Чтобы сделать это, наберите:

Как видите, это работает должным образом.

Символ «^» говорит awk ограничить поиск началом поля. Часть «field_num ~» указывает, что искать нужно только во втором столбце.

Вывести последовательности, которые не совпадают с шаблоном, можно при помощи символа «!», указанного перед тильдой (~). Данная команда выведет все строки, которые не начинаются с «sa».

Чтобы вывести строки, для которых верно предыдущее выражение и порядковый номер которых меньше 5, используйте условный оператор:

Это выполняет несколько новых действий. Так, оператор && дает возможность задавать дополнительные требования.  Таким образом можно объединить произвольное количество условий для поиска нужной строки.

Этот оператор используется для того, чтоб проверить, что значение первого столбца меньше, чем 5.

Автозаполнение многоязычного поиска с помощью запросов фраз Ngram и EDismax — Иван Провалов, Netflix

У меня есть файл, содержащий следующие строки:

В приведенном выше выводе я хочу извлечь 3 поля (номер 2, 4 и последнее. ). Я получаю следующий результат:

Как мне также извлечь последнее поле с доменным именем, которое находится после ? Как мне использовать извлечь поле?

2 Чтобы ответить на мой вопрос, который такой же, но другой, awk поглощал поля, когда они были пустыми, что мешало нумерации полей. Я изменился -F ‘ ‘ к -F ‘&lsqb; &rsqb;’ а также awk больше не глотал пустые поля.

Разделитель может быть регулярным выражением.

Производит:

42 Конечно, процесс не требуется: . Кроме того, было бы аккуратнее использовать разделитель выходных полей: 17 Разделители AWK могут быть регулярными выражениями ..

это сделало мой день! 4 @ das.cyklone: ​​awk также может иметь несколько разделителей, с : ex: (полезно иметь слова / строки, разделяющие вещи) (обратите внимание, что это сохраняет пробелы в полях между двумя разделителями. Добавление также может быть полезно, но может усложнить задачу ..

так как часто есть пробелы до и после ‘this’, это приведет к появлению 2 дополнительных пустых полей между пробелами и ‘this’) Я пробовал это на двух разных дистрибутивах, и у меня такое же поведение: я хочу получить порт из netstat -ntpl «netstat -ntpl | sed ‘s /: / /’ | awk ‘{print $ 5}'» работает, но можно было бы обойтись без двойного конвейера. Это работает, но я не ожидал данных в поле 17: «netstat -ntpl | awk -F» |: «‘{print $ 17}'» 2 да … это дало мне то, что я хотел: awk -F «&lsqb;:&rsqb; +» ‘/ \ / postmaster * $ / {print $ 5}’

Хорошие новости! разделитель полей может быть регулярным выражением. Вам просто нужно использовать :

Возврат:

Вот:

  • устанавливает разделитель поля ввода на любой или . Затем он устанавливает разделитель поля вывода на табуляцию.

  • использует флаг для установки переменной. — это переменная по умолчанию для разделителя поля вывода, для которой установлен символ табуляции. Флаг необходим, потому что нет встроенного для OFS типа .

  • печатает 3-е, 5-е и последнее поля на основе разделителя полей ввода.

См. Другой пример:

В этом файле есть два разделителя полей, а также . Если мы хотим напечатать второе поле независимо от того, является ли разделитель одним или другим, давайте сделаем оба разделителями!

Где файлы пронумерованы следующим образом:

1 Спасибо @BUFU за ваше редактирование. Я удалил ссылку на OFS, чтобы сосредоточиться на части FS, но это тоже хорошо. Ура!

Если ваш пробел согласован, вы можете использовать его как разделитель, а также вместо вставки напрямую, вы можете установить выходной разделитель, и он будет включен автоматически:

Другой — использовать параметр -F, но передать его регулярное выражение для печати текста между левой и правой круглыми скобками. .

Содержание файла:

Команда:

результат:

Использование awk для печати текста между :

Использовать но не будет работать.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html

1 Ваш ответ попал в очередь на удаление, потому что в 9 случаях из 10 пользователи с 1 репутацией, ссылающиеся на собственный блог, обычно являются спамом. Но ваш — исключение из правил. Последние 10 лет контента — это золотая жила, надеюсь, у вас есть план увековечить его.

Для разделителя полей любого числа через или письмо или или пробел, где разделительный знак должен повторяться не менее 2 раз и не более 6 раз, например:

Я уверен, что существуют варианты этого с использованием () и параметров

Однострочный Perl:

Используются следующие параметры командной строки:

  • обведите каждую строку входного файла, поместите строку в переменная, не печатать автоматически каждую строку

  • удаляет символы новой строки перед обработкой и добавляет их после

  • режим autosplit perl автоматически разделит входные строки на массив. По умолчанию разделение на пробелы

  • модификатор autosplit, в этом примере разбивается на или

  • выполнить код Perl

Perl тесно связан с awk, однако массив autosplit начинается с индекса а поля awk начинаются с $ 1.

Я вижу, что на доске много идеальных ответов, но все же хочу загрузить свой фрагмент кода,

2 print $3 ‘ ‘ $5 ‘ ‘ $7 можно напечатать так же, как print $3, $5, $7. Кроме того, я не вижу преимущества использования awk и последующего подключения к sed. В общем, awk может быть достаточно, и другие ответы показывают это.

Часть вторая: Что может делать AWK?

Главная цель в жизни AWK – это манипулировать её вводом на построчной основе. Программа awk обычно работает в стиле

Обработать строку. Двигаться дальше
Обработать строку. Двигаться дальше
Обработать строку…

Если то, что вы хотите сделать, не вписывается в эту модель, значит awk, может быть, не подходит к вашей задумке.

Обычный используемый в программировании awk синтаксис можно описать так:

awk образец {команда(ы)}

Это означает, что

«Посмотреть на каждую строку ввода, нет ли там ОБРАЗЦА. Если он там есть, запустить то, что между {}»

Можно пропустить или ОБРАЗЕЦ или КОМАНДУ

Если не указать образец, то команда будет применяться к КАЖДОЙ строке.

Если пропущена команда, то это эквивалентно указанию (просто напечатать строку):

{ print }

Конкретные примеры:

awk '/#/ {print "В этой строке есть комментарий"}' /etc/hosts

будет печатать «В этой строке есть комментарий» для каждой строки, которая содержит хотя бы один ‘#’ в любом месте строки в /etc/hosts

Модификация для наглядности

awk '/#/ {print $0 ":\tВ этой строке есть комментарий"}' /etc/hosts

Элемент ‘//’ в образце – это один из способов задать совпадение. Есть также другие способы задать, совпадает ли строка. Например,

awk '$1 == "#" {print "строка начинается с хеша"}' /etc/hosts

будет соответствовать строкам, первый столбец в которых является единичным ‘#’. Последовательность символов ‘==’ означает ТОЧНОЕ СОВПАДЕНИЕ ВСЕГО первого столбца.

Модификация для наглядности:

awk '$1 == "#" {print $0 "\tстрока начинается с хеша"}' /etc/hosts

С другой стороны, если вы хотите частичное совпадение конкретного столбца, используйте оператор ‘~’

awk '$1 ~ /#/ {print "ГДЕ-ТО в столбце 1 есть хеш"}' /etc/hosts

ПОМНИТЕ, ЧТО ПЕРВЫЙ СТОЛБЕЦ МОЖЕТ БЫТЬ ПОСЛЕ БЕЛОГО ПРОБЕЛА.

Модификация для наглядности:

awk '$1 ~ /#/ {print $0 "\tГДЕ-ТО в столбце 1 есть хеш"}' /etc/hosts

Ввод «# comment» будет соответствовать

Ввод » # comment» будет ТАКЖЕ соответствовать

Если вам нужно конкретное совпадение «строка, которая начинается точно с # и пробела», вы должны использовать

awk '/^# / {делай что-то}'

Множественное совпадение

Awk обработает ВСЕ ОБРАЗЦЫ, которые соответствуют текущей строке. Поэтому если использовать следующий пример,

  awk '
     /#/ {print "Есть комментарий"}
     $1 == "#" {print "Комментарий в первом столбце"}
     /^# /  {print "Комментарий в самом начале"}
   ' /etc/hosts

ТРИ записи будет выведено для строки вроде следующей:

# This is a comment

ДВЕ записи для

  # This is an indented comment

и только одна для

1.2.3.4 hostname # a final comment

Отслеживание контекста

Не все строки созданы равными, даже если они выглядят одинаково. Иногда вы хотите сделать что-то со строкой в зависимости от строк, которые идут перед ней.

Здесь быстрый пример, который печатает строки «ADDR» если вы не в секции «secret»

   awk '

   /secretstart/  	{ secret=1}
   /ADDR/		{ if(secret==0) print $0 } /* $0 – это полная строка */
   /secretend/		{ secret=0} '

Следующее напечатает содержимое, которое содержит внутри «ADDR» кроме случаев, если была увидена строка «secretstart». ПОРЯДОК ИМЕЕТ ЗНАЧЕНИЕ. Например, если записать так:

   awk '

   /ADDR/		{ if(secret==0) print $0 } /* $0 – это полная строка */
   /secretstart/  	{ secret=1}

   /secretend/		{ secret=0} '

и дать следующий ввод

ADDR a normal addr
secretstart ADDR a secret addr
ADDR another secret addr
a third secret ADDR
secretend
ADDR normal too

то будет напечатан первый «secret» addr. При том, что первоначальный пример скроет оба секрета.

Циклы

awkCdo-while, while, for

Цикл do-while имеет вид

do {
    тело цикла
} while (условие)

Цикл while имеет вид

while (условие) {
      тело цикла
}

Цикл for имеет две формы в awk: одна — традиционная:

for(инициализация; условия; завершение){
    тело цикла
}
for(index in list){
    тело цикла
}

listforlist

В приведенных конструкциях фигурные скобки {} необязательны
если тело цикла представляет собой один оператор.

В отличие от C
язык awk содержит две формы операторов досрочного
прерывания цикла и досрочного перехода к следующему выполнению тела
цикла.
Это связано с тем, что сама конструкция awk подразумевает
неявный внешний цикл: чтение данных — обработка.

Для досрочного прекращения этого процесса обработки служит оператор
exit.
Он по сути дела эквивалентен прерыванию текущих операций обработки
и чтению признака конца входного файла (EOF для C-патриотов).
Если в awk-программе есть
действия, ассоциированные с образом END, они будут выполнены.

Для досрочного прерывания процесса обработки текущей записи
(и запуска новой операции чтения — обработки) служит оператор next.
Для управления циклами, в явном виде содержащимися в
awk-программах, служат операторы break, continue.
Оператор break
прекращает
выполнение цикла, continue запускает новое исполнение тела цикла.

К операторам управления последовательностью операций с некоторой
натяжкой можно отнести и return — оператор возврата из функции,
описанной программистом.
Оператор

    return выражение

позволяет сообщить вызывающей программе
в качестве значения функции вычисленные значения выражения.

Массивы

awkCFortranAawk

Например, если перед вами стоит задача разобрать текстовый файл-таблицу,
в которой, скажем, в первом столбце находится фамилия работника,
получившего вознаграждение, обьем которого находится в седьмом столбце
таблицы и трубуется определить суммарное вознаграждение для каждого
из работающих, awk решает эту задачу с потрясающей легкостью:

    { payoff += $">7 }

и проблема остается лишь в выводе значений массива payoff
по завершению работы программы.

Конечно, для такого понятия массива трудно ввести предварительное
декларирование и элементы массивов в awk создаются в момент
использования.
По исчерпыванию необходимости в этом элементе,
от него можно в явном виде избавиться при помощи оператора
delete:

    delete payoff

и освободить память для более важных дел.
Удалить весь массив payoff можно командой

    delete payoff

Определение множества индексов данного массива и
обход элементов массива можно произвести с помощью ассоциативного
цикла, уже упомянутого выше.
Отрывок awk-программы

END	{
	for(name in payoff)
		printf name, payoff
	}

Единственным недостатком такого простого решения являетя неопределенный
порядок индексов массива payoff,
в связи с чем их имена почти наверняка не будут выведены в алфавитном
порядке !

Простым выходом из положения будет запуск какой-либо внешней программы
сортировки текстовых файлов, которая достаточно разумна для того,
чтобы знать о существовании русского алфавита.

Еще одним часто встречающимся способом порождения массивов
является использование встроенной функции split.
Эта функция может иметь два или три аргумента и используется для
разбиение какой-либо строки на отдельные части, заполняющие собой
массив.

Например, оператор

    n = split("31.12.1999", date, ".")

разобьет строку "31.12.1999" на три части
"31", "12", "1999", используя в качестве разделителя символ "."
и присвоит массиву date значения:

date = "31", date = "12", date = "1999".

n3

Если функция split вызывается с двумя аргуменами,
подразумевается, что символом-разделителем является значение
встроенной переменной awk FS — по умолчанию пробельный символ.

Таким образом

    nn = split($0, tokens)

в явном виде выполнит ту работу, что awk делает по умолчанию:
разделит входную строку () на отдельные элементы и запишет их
в массив tokens.
Количество элементов будет запомнено, как значение переменной nn.

Это полностью эквивалентно явному циклу

	for(i = 1; i <= NF; i++)
		tokens = $i
	nn = NF

Синтаксис команды awk

Сначала надо понять как работает утилита. Она читает документ по одной строке за раз, выполняет указанные вами действия и выводит результат на стандартный вывод. Одна из самых частых задач, для которых используется awk — это выборка одной из колонок. Все параметры awk находятся в кавычках, а действие, которое надо выполнить — в фигурных скобках. Вот основной её синтаксис:

$ awk опции ‘условие {действие}’

$ awk опции ‘условие {действие} условие {действие}’

С помощью действия можно выполнять преобразования с обрабатываемой строкой. Об этом мы поговорим позже, а сейчас давайте рассмотрим опции утилиты:

  • -F, —field-separator — разделитель полей, используется для разбиения текста на колонки;
  • -f, —file — прочитать данные не из стандартного вывода, а из файла;
  • -v, —assign — присвоить значение переменной, например foo=bar;
  • -b, —characters-as-bytes — считать все символы однобайтовыми;
  • -d, —dump-variables — вывести значения всех переменных awk по умолчанию;
  • -D, —debug — режим отладки, позволяет вводить команды интерактивно с клавиатуры;
  • -e, —source — выполнить указанный код на языке awk;
  • -o, —pretty-print — вывести результат работы программы в файл;
  • -V, —version — вывести версию утилиты.

Это далеко не все опции awk, однако их вам будет достаточно на первое время. Теперь перечислим несколько функций-действий, которые вы можете использовать:

  • print(строка) — вывод чего либо в стандартный поток вывода;
  • printf(строка) — форматированный вывод в стандартный поток вывода;
  • system(команда) — выполняет команду в системе;
  • length(строка) — возвращает длину строки;
  • substr(строка, старт, количество) — обрезает строку и возвращает результат;
  • tolower(строка) — переводит строку в нижний регистр;
  • toupper(строка) — переводить строку в верхний регистр.

Функций намного больше, но чтобы не загромождать статью я привел только те, которые мы будем использовать сегодня, а также ещё несколько для чтобы вы могли оценить масштаб возможностей утилиты.

В функциях-действиях можно использовать различные переменные и операторы, вот несколько из них:

  • FNR — номер обрабатываемой строки в файле;
  • FS — разделитель полей;
  • NF — количество колонок в данной строке;
  • NR — общее количество строк в обрабатываемом тексте;
  • RS — разделитель строк, по умолчанию символ новой строки;
  • $ — ссылка на колонку по номеру.

Кроме этих переменных, есть и другие, а также можно объявлять свои.

Условие позволяет обрабатывать только те строки, в которых содержатся нужные нам данные, его можно использовать в качестве фильтра, как grep. А ещё условие позволяет выполнять определенные блоки кода awk для начала и конца файла, для этого вместо регулярного выражения используйте директивы BEGIN (начало) и END (конец). Там ещё есть очень много всего, но на сегодня пожалуй достаточно. Теперь давайте перейдем к примерам.

Часть седьмая: AWK и оболочки (sh/ksh/bash/csh)

Иногда функционала AWK может быть недостаточно. В этом случае можно интегрировать awk в скрипт оболочки. Далее несколько примеров как это можно сделать.

Простой вывод

Иногда хочется использовать awk просто как программу форматирования, и сбрасывать вывод прямо пользователю Следующий скрипт принимает в качества аргумента имя пользователя и использует awk для дампа информации о нём из /etc/passwd.

Примечание: обратите внимание, что в скрипте одинарные кавычки раскрываются (а не являются вложенными) и между двумя раскрытыми парами одинарных кавычек стоит переменная $1 (вторая), которая в данном случае является аргументом скрипта, в то время как $1 является частью синтаксиса $1 (означает первое поле в строке).

#!/bin/sh

while  ; do
	awk -F: '$1 == "'$1'" { print $1,$3} ' /etc/passwd
	shift
done

Присвоение переменным оболочки вывода awk

Иногда мы хотим использовать awk просто для быстрого способа установить значение переменной. Используя тему passwd, у нас есть способ узнать шелл для пользователя и увидеть, входит ли он в список официальных оболочек.

И опять, обратите внимание, как происходит закрытие одинарных кавычек в выражении awk, После закрытой (второй) кавычки, $1 является переменной, в которую передано значение первого аргумента скрипта, а не частью синтаксиса awk.

#!/bin/sh

user="$1"
if  ; then echo ERROR: need a username ; exit ; fi

usershell=`awk -F: '$1 == "'$1'" { print $7} ' /etc/passwd`
grep -l $usershell /etc/shells
if  ; then
        echo ERROR: shell $usershell for user $user not in /etc/shells
fi

Другие альтернативы:

# Смотрите "man regex"
usershell=`awk -F: '/^'$1':/ { print $7} ' /etc/passwd`
echo $usershell;

# Только современные awk принимают -v. Вам может понадобиться использовать "nawk" или "gawk"
usershell2=`awk -F: -v user=$1 '$1 == user { print $7} ' /etc/passwd`
echo $usershell2;

Объяснение дополнительных вышеприведённых методов остаётся домашним заданием читателю

Передача данных в awk по трубе

Иногда хочется поместить awk в качестве фильтра данных, в большую программу или команду в одной строке, вводимую в запрос оболочки. Пример такой команды в скрипте (в качестве аргументов скрипта передаётся список файлов логов веб-сервера, поскольку запись в журнал настраивается и логи могут иметь различную структуру, для работоспособности в конкретных случаях может понадобиться подправить команды):

#!/bin/sh

grep -h ' /index.html' $* | awk -F\" '{print $4}' | sort -u

Преобразование wav файлов в mp3

# Скрипт создает структуру каталогов в другом месте
# затем ищет все wav файлы в указанной директории, определяет что они не сжатые
# сжимает их, причем имя становится name.wav.mp3, то есть к имени файла добовляется .mp3,
# а оригиналы копирует в подготовленное дерево дирикторий

#Переходим в каталог
cd "/home/samba/archives/Архив\ рекламы\ 2004/"
#создаем структуру каталогов в /home/samba1/Архив рекламы 2004/
find ./ -type d | awk '{system ("mkdir -p \"/home/samba1/Архив рекламы 2004/"$0"\"")}'
#ищем все wav файлы, сжимает их, а оригиналы копирует в подготовленное дерево дирикторий
find ./ | grep -i .wav$ \
| awk '{system ("file \""$0"\""); print $0}' \
| awk '/PCM/ {getline; system ("/usr/local/bin/lame -m s -b 256 \""$0"\" \""$0".mp3\" && mv \""$0"\" \"/home/samba1/Архив рекламы 2004/"$0"\"")}'

Для чего нужен awk?

awk – это утилита/язык для извлечения данных. Именно awk являлся источником вдохновения для Larry Wall, когда он создавал Perl. Для выполнения различных практических задач по обработке текста awk часто используется совместно с sed. В зависимости от поставленной задачи вы можете использовать либо awk, либо Perl, хотя это в большей степени зависит от личных предпочтений. Как и sed, awk читает за один раз одну строку, выполняет определенные действия в зависимости от заданных опций, и выводит результат. Одним из самых простых и популярных способов использования awk является выбор столбца из текстового файла или из вывода другой команды. Когда я устанавливал Debian на свою вторую рабочую станцию, я использовал awk для того, чтобы получить список установленных на первой машине, и скормить его aptitude. Я делал это с помощью команды вида:

$ dpkg -l | awk ‘ {print $2} ‘ > installed

В настоящее время большинство менеджеров пакетов предоставляют такую возможность, например это можно сделать с помощью команды rpm’s -qa, но вывод содержит больше информации, чем мне нужно. Я вижу, что второй столбец вывода dpkg -l содержит названия установленных пакетов, поэтому я использовал вышеприведенную команду, чтобы извлечь только второй столбец.

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: