Регулярные выражения (англ. regular expressions, сокращённо regex) — это система поиска фрагментов в тексте, основанная на специальной системе записи образцов для поиска. Образец (англ. pattern), задающий правило поиска, также называют шаблоном или маской.
Сейчас регулярные выражения используются многими текстовыми редакторами и утилитами для поиска и изменения текста на основе выбранных правил. Многие языки программирования имеют встроенную поддержку работы с регулярными выражениями, для других они доступны как внешние библиотеки. Набор утилит (включая редактор sed и фильтр grep), поставляемых в дистрибутивах *nix, одним из первых способствовал распространению регулярных выражений.
Регулярные выражения используются для сжатого описания некоторого множества строк с помощью шаблонов, без необходимости перечисления всех элементов этого множества. При составлении шаблонов используется специальный синтаксис, поддерживающий, обычно, следующие операции:
● Перечисление: вертикальная черта разделяет допустимые варианты. Например, «one|two» соответствует one или two.
|
|
● Группировка: круглые скобки используются для определения области действия и приоритета операторов. Например, шаблоны «abd|acd» и «a(b|c)d» описывают одно и то же множество, abd и acd.
● Квантификация: квантификатор после символа или группы определяет, сколько раз предшествующее выражение может встречаться. Например:
● {m,n} — общее выражение, повторений может быть от m до n включительно.
● {m,} — общее выражение, m и более повторений.
● {,n} —общее выражение, не более n повторений.
●? (вопросительный знак) означает 0 или 1 раз, то же самое, что и {0,1}. Например, «colou?r» соответствует и color, и colour.
● * (астериск) означает 0, 1 или любое число раз ({0,}). Например, «go*gle» соответствует ggle, gogle, google и т.д.
● + (плюс) означает хотя бы 1 раз ({1,}). Например, «go+gle» соответствует gogle, google и т.д. (но не ggle).
Конкретный синтаксис регулярных выражений зависит от их программной реализации. Мы будем рассматривать синтаксис «базовых» регулярных выражений UNIX. Хотя он на данный момент и определён POSIX как устаревший, но до сих пор широко распространён из соображений обратной совместимости. Многие UNIX-утилиты используют такие регулярные выражения по умолчанию.
В этом синтаксисе большинство символов соответствуют сами себе («a» соответствует a и т.д.). Исключения из этого правила называются метасимволами:
. | Соответствует любому единичному символу. |
[ ] | Соответствует любому единичному символу из числа заключённых в скобки. Символ - (дефис) интерпретируется буквально только в том случае, если он расположен непосредственно после открывающей или перед закрывающей скобкой: [abc-] или [-abc]. В противном случае, он обозначает интервал символов. Например, [abc] соответствует a, b или c. [0-9] соответствует цифрам. |
[^ ] | Соответствует единичному символу из числа тех, которых нет в скобках. Например, [^abc] соответствует любому символу, кроме a, b или c. [^0-9] соответствует любому символу, кроме цифр. |
^ | Используемое в начале регулярного выражения, соответствует началу строки текста. |
$ | Используемое в конце регулярного выражения, соответствует концу строки текста. |
\(\) | Объявляет «отмеченное подвыражение», которое может быть использовано позже. |
\n | n — цифра от 1 до 9, соответствует n-му отмеченному подвыражению. |
* | Звёздочка после выражения, соответствующего единичному символу, соответствует нулю или более копий этого выражения. Например, «[xyz]*» соответствует пустой строке, x, y, zx, zyx, и т.д. |
\{x,y\} | Соответствует последнему блоку, встречающемуся не менее x и не более y раз. Например, «a\{3,5\}» соответствует aaa, aaaa или aaaaa. |
При использовании диапазонов символов следует учитывать, что они могут зависеть от выбранных настроек локализации. Например, диапазон «[b-e]» означает символы от b до e включительно. В английском языке, где сортировка букв идёт по-порядку (... XYZabcdefg...), ему соответствует набор символов b, c, d, e. Согласно правилам русского языка, сортировка тех же символов идёт в другом порядке (... эЭюЮяЯaAbBcCdDeEfFgG...), и тому же диапазону соответствуют символы b, B, c, C, d, D, e.
|
|
Для решения таких проблем в стандарте POSIX имеются объявления некоторых классов и категорий символов:
Класс | Диапазон для английского языка | Описание |
[:upper:] | [A-Z] | Латинские буквы верхнего регистра |
[:lower:] | [a-z] | Латинские буквы нижнего регистра |
[:alpha:] | [A-Za-z] | Латинские буквы верхнего и нижнего регистра |
[:alnum:] | [A-Za-z0-9] | Цифры, латинские буквы верхнего и нижнего регистра |
[:digit:] | [0-9] | Цифры |
[:xdigit:] | [0-9A-Fa-f] | Шестнадцатеричные цифры |
[:punct:] | [.,!?:…] | Знаки пунктуации |
[:blank:] | [ \t] | Пробел и табуляция |
[:space:] | [ \t\n\r\f\v] | Символы пропуска |
[:cntrl:] | - | Символы управления |
[:graph:] | [^\t\n\r\f\v] | Символы печати |
Способ представить сами метасимволы —., - [ ] и другие в регулярных выражениях без интерпретации, т.е. в качестве простых (не специальных) символов — предварить их обратной символом: \ (обратный слеш). Например, чтобы представить сам символ «точка» (просто точка, и ничего более), надо написать \. (обратный слеш, а за ним — точка). Чтобы представить символ открывающей квадратной скобки [, надо написать
\[ (обратный слеш, и следом за ним скобка [) и т.д. Сам метасимвол
\ (обратный слеш) тоже может быть защищен, то есть представлен как
\\ (два обратных слеша), и тогда интерпретатор регулярных выражений воспримет его как простой символ обратного слеша \.
При составлении регулярных выражений следует также учитывать их две основные черты: они являются т.н. «ленивыми» и «жадными». Первое означает, что в строке, где есть несколько совпадений с шаблоном, шаблон совпадёт с первым из них. Например, регулярное выражение
«шаблон\(..\)» для строки
в строке, где есть несколько совпадений с шаблоном, шаблон совпадёт с первым из них
вернёт в подвыражении \1 символы ом, соответствующие первому встретившемуся подходящему совпадению (шаблоном). Второе возможное место совпадения (шаблон с) рассмотрено не будет.
«Жадность» регулярных выражений заключается в том, что, при использовании квантификаторов * (астериск) и + (плюс), шаблон будет совпадать с максимально длинным из возможных вариантов. Для той же строки шаблон «шаблон.*н», означающий подстроку, начинающуюся с «шаблон», заканчивающуюся на «н» и с произвольным количеством (*) любых (.) символов между «шаблон» и «н», совпадёт с подстрокой
шаблоном, шаблон совпадёт с первым из н,
|
|
а не с более короткой
шаблоном, шаблон
Рассмотрим далее применение регулярных выражений на примерах использования утилит grep и sed.