Введение в регулярные выражения

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

Регулярное выражение – это образец, задающий правила  поиска соответствующих (иногда наоборот – несоответствующих) текстовых шаблонов. По сути это способ описания и разбора текста. Данное руководство дает общее представление о регулярных выражениях, не вдаваясь в подробности синтаксиса. Для объяснения понятий используется только команда egrep.

Регулярные выражения

Регулярные выражения состоят из символов двух типов:

  • регулярные буквальные символы;
  • метасимволы.

Именно благодаря метасимволам регулярные выражения такие мощные.

Для демонстрации примеров будет использоваться файл country.txt, где первый столбец – название страны, второй столбец – население, третий столбец – континент.

$ cat country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Argentina,36955182,Latin America
Brazil,172860370,Latin America
Cameroon,15421937,Africa
Japan,126549976,Asia

Анкоры

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

Итак, чтобы найти в файле все страны, название которых начинается с I, используется выражение:

$ egrep '^I' country.txt
India,1014003817,Asia
Italy,57634327,Europe

А чтобы найти все страны, расположенные на континенте, название которого заканчивается на e, используется выражение:

$ egrep 'e$' country.txt
Italy,57634327,Europe

Следующий метасимвол – это символ точки (.), который обозначает один любой символ в указанном месте. То есть, чтобы найти все строки, содержащие названия стран, которые состоят ровно из 5 символов:

$ egrep '^.....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Japan,126549976,Asia

Что, если нужно найти все названия стран, начинающиеся с I или J и состоящие из 5 символов?

$ egrep '^[IJ]....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia

Квадратные скобки ([ ]) содержат набор или класс символов, любой из которых может находиться в указанном месте.

Символ вставки (^), внесенный в квадратные скобки, исключает указанный за ним набор символов. Следующая строка ищет названия стран длиной в 5 символов, которые не начинаются с I или J.

$ egrep '^[^IJ]....,' country.txt
Yemen,1184300,Asia

Группирование и чередование

Для группирования выражений используются круглые скобки. Для обозначения чередования используется символ вертикальной черты  «|». Итак, чтобы вывести все строки, содержащие слова «Asia» или «Africa», нужно ввести:

$ egrep 'Asia|Africa' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia

Также это можно оставить общие символы этих слов (A и a), а остальное взять в скобки:

$ egrep 'A(si|fric)a' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia

Кванторы

Кванторы – это метасимволы, указывающие частоту повторения определенного символа. Для указания количества повторения символа используются фигурные скобки ({ }).

То есть, вместо строки:

$ egrep '^[IJ]....,' country.txt

можно набрать:

$ egrep '^[IJ].{4},' country.txt

где фигурные скобки выступают в качестве кванторов.

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

$ egrep '^[IJ].{4,6},' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia

Данный синтаксис используется для поиска стран, названия которых начинаются с I или J и состоят из 4-6 символов.

При работе с кванторами можно использовать «горячие клавиши». Например:

  • выражение {0,1} эквивалентно символу ?. То есть, строка

$ egrep '^ab{0,1}c$' filename

аналогична строке

$ egrep '^ab?c' filename

  • выражение {0,} эквивалентно символу *. То есть, строка

$ egrep '^ab{0,}c$' filename

аналогична строке

$ egrep '^ab*c' filename

  • выражение {1,} эквивалентно символу +. Строка

$ egrep '^ab{1,}c$' filename

равна строке

$ egrep '^ab+c' filename

Ознакомьтесь с примерами использования приведенных выше выражений. Теперь вместо поиска по файлу нужно искать со стандартного ввода. Хитрость такого подхода состоит в том, что при поиске шаблона grep (или egrep) будет полностью выводить строку, содержащую данный шаблон.

К примеру, нужно найти все возможные способы написания предложения «the grey colour suit was his favourite».

Для этого используется выражение:

$ egrep 'the gr[ea]y colou?r suit was his favou?rite'
the grey color suit was his favourite
the grey color suit was his favourite
the gray colour suit was his favorite
the gray colour suit was his favorite

Проанализировав данное выражение, можно заметить, что:

  • слово «grey» имеет 2 варианта написания (grey и gray), и чтобы найти все варианты его написания, использовалось [ea];
  • слово «colour» также пишется как «color», то есть, «u» пишется не всегда, потому нужно использовать u?;
  • аналогично, слово «favourite» также пишется как «favorite», потому его нужно было написать как favou?rite.

Для примера можно также вывести совпадения почтового индекса США:

$ egrep '^[0-9]{5}(-[0-9]{4})?$'
83456
83456
83456-
834562
92456-1234
92456-1234
10344-2342-345

Также можно искать правильное время в 24-часовом формате.

$ egrep '^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]'
23:44:02
23:44:02
33:45:11
15:45:33
15:45:33

В приведенном выше примере говорится, что если первая цифра – 0 или 1, то вторая будет от 0 до 9. Но если первая цифра – 2, то вторая будет 0,1,2 или 3.

Границы последовательности

Чтобы создать шаблон, соответствующий словам, которые заканчиваются на «color» (такие, как unicolor, watercolor, multicolor, и т.д.,), но не совпадающий со словами, которые начинаются с «color» (например, colorless или colorful), используется строка:

$ egrep 'color\>'

Следующая строка меняет границы последовательности, и теперь шаблон соответствует словам colorless или colorful, но не unicolor, watercolor, multicolor и т.д.

$ egrep '\<color'

Чтобы шаблон точно соответствовал слову «color», используйте:

$ egrep '\<color\>'

Обратные ссылки

При необходимости найти все дважды введенные слова (the the или before before) используются обратные ссылки — способ обнаружения повторяющегося символа путем запоминания шаблона.

К примеру:

$ egrep "\<the\> \1"

Универсальный способ поиска повторяющегося символа:

$ egrep "\<(.*)\> \1"

Приведенный выше пример можно использовать для поиска названий, первый и последний символ которых одинаковые.

Если в шаблоне больше, чем одна пара скобок, то на последующие скобки можно сослаться при помощи \2, \3, \4 и т.д.

Это только основы работы с регулярными выражениями. Чтобы получить более подробные инструкции по их использованию, читайте руководство «Использование Grep и регулярных выражений для поиска текстовых шаблонов в Linux».

Tags: