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

Регулярное выражение — текстовый шаблон, состоящий из комбинации букв, цифр и спецсимволов, известных как метасимволы. Близким родственником регулярных выражений являются выражения из групповых символов, часто используемые в управлении файлами. Регулярные выражения используются, в основном, для сравнения текста и поиска. Широко используются для разбора синтаксиса.

Пользователи UNIX знакомы с регулярными выражениями по программам grep, sed, awk (или gawk) и ed. С помощью этих программ или их аналогов можно опробовать и проверить приводимые ниже примеры. Текстовые редакторы, такие как (X)Emacs и vi, также активно используют регулярные выражения. Возможно, самое известное и самое широкое использование регулярных выражений имеет место в языке Perl. Без знания регулярных выражений трудно обойтись разработчику ПО и системному администратору.

Далее рассмотрим сами регулярные выражения.

Метасимволы

Итак, строки могут состоять из букв, цифр и метасимволов. Метасимволами являются:

\ | ( ) [ ] { } ^ $ * + ? . < >

Метасимволы могут играть в регулярном выражении следующие роли:

  • квантификатор
  • утверждение;
  • знак группы;
  • альтернатива;
  • знак последовательности

Квантификаторы

Метасимвол * (звездочка) заменяет собой 0 или несколько символов. Метасимвол + (плюс) заменяет собой 1 или несколько символов. Метасимвол . (точка) заменяет собой ровно 1 произвольный символ. Метасимвол ? (вопросительный знак) заменяет собой 0 или 1 символ. Различие в использовании * и + таково, что запрос на поиск строки с* даст любые строки, включая пустые, а запрос с+ — только строки, содержащие символ с.

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

В регулярных выражениям используется также конструкция {n,m}, обозначающая, что символ, идущий перед конструкцией, встречается в строке от n до m раз. Опуская число m подразумеваем бесконечность. Т.е. частными случаями конструкции являются следующие записи: {0,}, {1,} и {0,1}. Первая соответствует *, вторая — метасимволу +, а третья — ?. Эти равенства легко получить из определения соответствующих квантификаторов. Кроме того, конструкция {n} означает, что символ встречается ровно n раз.

В связи с использованием в качестве метасимволов некоторых знаков препинания и математических символов введен дополнительный метасимвол \ (backslash, обратная косая черта), который будучи записан перед метасимволом превращает последний в обычный символ. Т.е. ? — это квантификатор, а \? — знак вопроса.

Группы

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

Пример:

( ?ho)+

означает (или заменяет собой)

ho
ho ho
ho ho ho
hohoho

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

Альтернативы

Образуются при помощи метасимвола | (вертикальная черта), обозначающего логическое «или».

Пример: регулярное выражение коров(а|ы|е|у|ой|ою)? задает все возможные склонения слова «корова» в единственном числе по падежам.

Утверждения

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

^
начало строки
$
конец строки
<
начало слова
>
конец слова

Пример: регулярное выражение $The позволяет найти строку, начинающуюся с The.

Замечание: обычные символы можно рассматривать как утверждения с ненулевой длиной.

Последовательности

Особая конструкция, заключенная в метасимволы [ и ] (прямоугольные скобки), позволяет перечислить варианты символов, которые могут стоять в регулярном выражении на данном месте, и называется последовательностью. Внутри прямоугольных скобок все метасимволы трактуются как простые символы, а символы - (минус) и ^ приобретают новые значения: первый позволяет задать непрерывную последовательность символов между двумя указанными, а второй дает логическое «не» (отрицание). Проще всего рассмотреть следующие примеры:

какая-либо из строчных латинских букв:

[a-z]

латинский буквенно-цифровой символ (от a до z, от A до Z и от 0 до 9):

[a-zA-Z0-9]

символ, не являющийся латинским буквенно-цифровым:

[^a-zA-Z0-9]

любое слово (без дефисов, математических символов и цифр):

<[a-zA-Z]+>

Для краткости и простоты вводятся следующие сокращения:

\d
цифра (т.е. соответствует выражению [0-9]);
\D
не цифра (т.е. [^0-9]);
\w
латинское слово (буквенно-цифровое);
\W
последовательность символов без пробелов, не являющаяся латинским буквенно-цифровым словом ([^a-zA-Z0-9]);
\s
пустой промежуток [ \t\n\r\f], т.е. пробелы, табуляция и т.д.
\S
непустой промежуток ([^ \t\n\r\f]).

Связь с групповыми символами

С групповыми символами знаком, наверное, каждый пользователь. Примером выражения с использованием группового символа является запись *.jpg, обозначающая все файлы с расширением jpg. Чем же регулярные выражения отличаются от групповых символов? Отличия можно суммировать в трех правилах преобразования произвольного выражения с групповыми символами в регулярное выражение:

  1. Заменить * на .*
  2. Заменить ? на .
  3. Заменить все символы, совпадающие с метасимволами, на их бэкслэшированные варианты.

Действительно, в регулярном выражении запись * бесполезна и дает пустую строку, т.к. означает, что пустая строка повторяется сколь угодно раз. А вот .* (повторить произвольный символ сколь угодно много раз, включая 0) как раз совпадает по смыслу с символом * в множестве групповых символов.

Регулярное выражение, соответствующее *.jpg, будет выглядеть так: .*\.jpg. А, например, последовательности групповых символов ez*.[ch]pp соответствуют два эквивалентных регулярных выражения — ez.*\.[ch]pp и ez.*\.(cpp|hpp).

Примеры регулярных выражений

E-mail в формате xxx@mmmm.yyy

[a-z0-9_-]+(\.[a-z0-9_-]+)*@[a-z0-9_-]+(\.[a-z0-9_-]+)+

E-mail в формате "Иван Иванов <ivanov@dsgfhsd.ru>"

("?[a-zA-Z]+"?[ \t]*)+\<[a-z0-9_-]+(\.[a-z0-9_-]+)*@[a-z0-9_-]+(\.[a-z0-9_-]+)+\>

Проверка web-протокола в URL (http://, ftp:// или https://)

[a-z]+://

Некоторые команды и директивы C/C++:

^#include[ \t]+[<"][^>"]+[">] — директива include

//.+$ — комментарий на одной строке

/\*[^*]*\*/ — комментарий на нескольких строках

-?[0-9]+\.[0-9]+ — число с плавающей точкой

0x[0-9a-fA-F]+ — число в шестнадцатиричной системе счисления.

А вот, например, программа поиска слова cow:

  grep -E "cow|vache" * >/dev/null && echo "Found a cow"

Здесь опция -E используется для включения поддержки расширенного синтаксиса регулярных выражений.

Текст составлен на основе статьи Жана Борсоди (Jan Borsodi) из файла HOWTO-regexps.htm

Печать/экспорт