Linux awk поиск в строке

Использование языка AWK для работы с текстом в Linux

Утилиты Linux часто повторяют принципы работы Unix. Инструменты стремятся к простоте, используют обычные текстовые файлы для ввода и вывода данных и работают по модульному принципу. Такое подражание также предоставляет огромные функциональные возможности обработки текста с помощью инструментов sed и awk.

Данное руководство описывает использование awk. Awk – это одновременно язык програмирования и текстовый процессор, предоставляющий несколько очень удобных способов обработки текстовых данных. Все примеры были выполнены на Ubuntu 12.04 VPS, но любая современная система Linux должна работать таким же образом.

Основной синтаксис

Команда awk включена во все современные дистрибутивы Linux по умолчанию, ее не нужно устанавливать.

Лучше всего аwk справляется с файлами, отформатированными предсказуемым образом. К примеру, эта команда особенно сильна в анализе и обработке табличных данных. Она работает путем построчного разбора всего файла.

По умолчанию для разделения полей она использует пробельные символы и символы табуляции. К счастью, большинство систем Linux используют такой формат.

Базовый формат команды awk:

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

Если был пропущен шаблон, awk выполнит указанное действие для всех строк.

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

Основы работы с awk

В своей простейшей форме awk, как и cat, просто выводит все строки текстового файла на экран.

Для примера попробуйте вывести файл fstab, содержащий список существующих файловых систем:

awk » /etc/fstab
# /etc/fstab: static file system information.
#
# Use ‘blkid’ to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
#
proc /proc proc nodev,noexec,nosuid 0 0
# / was on /dev/vda1 during installation
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1

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

Читайте также:  Dual band usb adapter 600 драйвер linux

awk ‘/UUID/’ /etc/fstab
# device; this may be used with UUID= as a more robust way to name devices
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1

Как видите, теперь awk вывела только строки, содержащие последовательность «UUID». Можно также избавиться от посторонних строк, указав, что последовательность «UUID» должна быть расположена в самом начале строки:

awk ‘/^UUID/’ /etc/fstab
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1

Аналогичным образом можно использовать часть «действие», чтобы указать, какую именно информацию нужно вывести. К примеру, чтобы вывести только первый столбец, наберите:

awk ‘/^UUID/ ‘ /etc/fstab
UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd

Также можно сослаться на каждый столбец (разделены пробелами) с помощью переменных, связанных с номером столбца. Так, на первый столбец можно сослаться, набрав $1; чтобы сослаться на всю строку, используйте $0.

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

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

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

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

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

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

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

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

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

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

Читайте также:  How to move folders in linux

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

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

awk ‘BEGIN < print "We can use awk like the echo command"; >‘
We can use awk like the echo command

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

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

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

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

echo «1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan
5 spaghetti jessica» > favorite_food.txt

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

awk ‘/sa/’ favorite_food.txt
1 carrot sandy
2 wasabi luke
3 sandwich brian
4 salad ryan

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

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

awk ‘$2 ~ /^sa/’ favorite_food.txt
3 sandwich brian
4 salad ryan

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

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

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

awk ‘$2 !~ /^sa/’ favorite_food.txt
1 carrot sandy
2 wasabi luke
5 spaghetti jessica

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

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

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

Заключение

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

Читайте также:  Linux анализ логов системы

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

Источник

Use Awk to extract substring

While the script running on one machine A produces aaa0 , running on machine B produces only aaa , without 0 in the end. Both machine runs Ubuntu/Linaro , but A runs newer version of awk(gawk with version 3.1.8 while B with older awk (mawk with version 1.2) I am asking in general, how to write a compatible awk script that performs the same functionality .

7 Answers 7

You just want to set the field separator as . using the -F option and print the first field:

$ echo aaa0.bbb.ccc | awk -F'.' '' aaa0 
$ echo aaa0.bbb.ccc | cut -d'.' -f1 aaa0 
$ echo aaa0.bbb.ccc | sed 's/[.].*//' aaa0 
$ echo aaa0.bbb.ccc | grep -o '^[^.]*' aaa0 

I am asking in general, how to write a compatible awk script that performs the same functionality .

To solve the problem in your quesiton is easy. (check others’ answer).

If you want to write an awk script, which portable to any awk implementations and versions (gawk/nawk/mawk. ) it is really hard, even if with —posix (gawk)

  • some awk works on string in terms of characters, some with bytes
  • some supports \x escape, some not
  • FS interpreter works differently
  • keywords/reserved words abbreviation restriction
  • some operator restriction e.g. **
  • even same awk impl. (gawk for example), the version 4.0 and 3.x have difference too.
  • the implementation of certain functions are also different. (your problem is one example, see below)

well all the points above are just spoken in general. Back to your problem, you problem is only related to fundamental feature of awk. awk » the line like that will work all awks.

There are two reasons why your awk line behaves differently on gawk and mawk:

  • your used substr() function wrongly. this is the main cause. you have substr($0, 0, RSTART — 1) the 0 should be 1 , no matter which awk do you use. awk array, string idx etc are 1-based.
  • gawk and mawk implemented substr() differently.

Источник

Оцените статью
Adblock
detector