Найти тему

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

Оглавление

Статья для: Mindstorm

Автор: Ippolid

Что такое ''регулярные выражения''?

Регулярные выражения, их еще называют regexp, или regex (regular expressions) — это формальный язык, который используется для поиска и манипуляций с подстроками в тексте. Их используют разработчики в коде приложения, тестировщики в автоматических тестах, да просто при работе в командной строке!

Чем это лучше простого поиска? Тем, что позволяет задать шаблон.

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

  • Проверка пароля на сложность:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*+=]).{8,}$
  1. Эта запись проверяет введённый пароль на следующие параметры:
  2. Его длина не менее 8 символов
  3. Содержит хотя бы одну цифру
  4. Содержит хотя бы одну заглавную букву
  5. Содержит хотя бы одну строчную букву
  6. Содержит хотя бы один специальный символ
  • Проверка введённого email:
/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/

Эта запись проверяет вводимые символы и длину каждой части вводимой почты

  • Регулярными выражениями можно пользоваться не только для валидации (проверки), но и для обработки данных, например, в блокноте. Вот практический пример такой обработки: скопировать номера регионов и перевести в формат PHP-массива.

Видео (Источник)

Regexp поддерживаются во многих языках программирования:

  • Python
  • Javascript
  • Go
  • Php
  • Rust
  • Java
  • C#
  • И многие другие

Однако для конкретного ЯП реализация может немного отличаться.

Синтаксис и использование

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

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

В этой статье будет краткий экскурс в основы Regехров.

Потренироваться в работе можно на следующих сайтах:

Регулярные выражения обычно записываются между двух слешей (/…/).

Представление символов

[xyz]-набор символов (или x или y или z p[ioa]p может соответствовать pip, pop, pap)
(xyz)-группа символов (ищет точное совпадение без или)
. — любой символ (h.llo соответствует hello, h1llo, h%llo и т. д.)
(^) — отрицание (в группе или наборе)
\d, [0-9]-все цифры (\D, [^0-9] — всё кроме цифр)
[a-z], [A-Z]-буквы английского алфавита
\s — пробельные символы (\S — не пробельные символы)
\w -буква или цифра (\W- не буква и не цифра)
^ — начало строки
$- конец строки
\b -символы в конце и начале слова (a\b — aa
a aa aa), \B -символы не в начале и не в конце
(a|b)- альтернатива (а или б — поп (a|ы) соответствуют попа, попы), используются внутри групп символов

Экранирование

Иногда нужно найти такие символы, как '\', '.', '^', но в регулярных выражениях они являются специальными.

Чтобы избавиться от этой проблемы, надо перед нужным нам символом поставить обратный слеш (\), тогда он будет опознаваться не как специальный.

Например a\\c соответствует a\с.

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

Квантификация — это поиск последовательностей. Квантификатор — это специальный ограничитель, который указывает количество возможных повторений символа, группы символов или класса символов, находящихся в регулярном выражении перед ним.

{n} — n повторений (ab{2} — соответствует abb)
{n, k}- от n до k включительно повторений
{n, } — от n до беск. повторений
{, k} — от 0 до k повторений
? — ноль или одно повторение
+ — одно и более повторение
*- ноль и более символов

По умолчанию квантификаторы жадные — захватывают максимально возможное число символов. Добавление `? ` делает их _ленивыми, они захватывают минимально возможное число символов

Группировки

Иногда нужно, чтобы выбранные в первой части символы повторились и во второй: tu-tu, ta-ta, а не tu-ta и наоборот.

В этом случаи нам поможет группировки и обратная связь

Одно из применений группировки — повторное использование ранее найденных групп символов. При обработке выражения подстро́ки, найденные по шаблону внутри группы, сохраняются в отдельной области памяти и получают номер, начиная с единицы (обычно до 9 номеров). Каждой подстроке соответствует пара скобок в регулярном выражении.

Впоследствии в пределах данного регулярного выражения можно использовать обозначения от \1 до \9 для проверки на совпадение с ранее найденной подстрокой.

Например, регулярное выражение (та|ту)-\1 найдёт строку та-та или ту-ту, но пропустит строку та-ту.

Квантификация группы трактуется как многократное сохранение подстроки под одним и тем же номером, то есть запоминается последнее вхождение: например, регулярное выражение (.)+\1 найдёт строку abcc, но пропустит abca.

Именованные группы

Если вы используете несколько групп, то не очень удобно запоминать их по номерам. Гораздо проще пользоваться именами. Для этого нужно добавить `? <имя>` после открытия скобки:

/(?<group1>ta|tu)-\k<group1>/
ta-tu ta-ta tu-tu

Теперь нам удобнее работать с группой в своем коде — можно ссылаться на группу по имени `group1`.

Символ k используется для обратной ссылки на именованную группу. В данном случае, `\k<group1>` означает обратную ссылку на группу с именем `group1`. Это означает, что после символа — должно быть то же самое значение, что и в группе `group1`.

Группировка без обратной связи

Если группа используется только для группировки и её результат в дальнейшем не потребуется, то можно использовать группировку вида (?:шаблон). Под результат такой группировки не выделяется отдельная область памяти и, соответственно, ей не назначается номер. Это положительно влияет на скорость выполнения выражения, но понижает удобочитаемость.

Атомарная группировка

Атомарная группировка вида (?>шаблон) так же, как и группировка без обратной связи, не создаёт обратных связей. В отличие от неё, такая группировка запрещает возвращаться назад по строке, если часть шаблона уже найдена.

Модификаторы

Модификаторы — это символы, которые указываются после знака `? ` в группе символов регулярного выражения и меняют их поведение.

i (ignore case): Этот модификатор делает регулярное выражение нечувствительным к регистру. Например, /abc/i будет соответствовать «ABC», «aBc», «AbC» и так далее.
g (global): Модификатор g используется для поиска всех совпадений в тексте, а не только первого. Если не используется, будет найдено только первое совпадение.
m (multiline): Этот модификатор позволяет регулярному выражению работать в режиме «многострочности», что означает, что символы начала и конца строки (^ и $) будут сопоставляться с началом и концом каждой строки в тексте, а не только всего текста.
s (dotall): Модификатор s позволяет точке. сопоставляться со всеми символами, включая переводы строк. Без этого модификатора точка обычно не сопоставляется с переводами строк.
u (unicode): Этот модификатор позволяет работать с юникодными символами. В регулярных выражениях, где есть символы Unicode, модификатор u обязателен.

Если после `? ` мы поставим `i`, то включим режим игнорирования регистра. Мы получим сопоставление еще одной подстроки, но уже не с `t` в нижнем регистре, а с `T` в верхнем:

/(? i: t.)-(? : t.)/
ta-tu ta-tTu-tu tu-T

Просмотр вперед и назад

Большинство реализаций регулярных выражений поддерживают две полезные функции:

  • Просмотр вперед — опережающий поиск (_lookahead_)
  • Просмотр назад — ретроспективный поиск (_lookbehind_)

Это позволяет производить поиск фрагмента текста, «просматривая» (но не включая в найденное) окружающий текст, который расположен до или после искомого фрагмента текста. Просмотр с отрицанием используется реже и «следит» за тем, чтобы указанные соответствия, напротив, не встречались до или после искомого текстового фрагмента.

таблица с википедии
таблица с википедии

Поиск по условию

Поиск по условию-это одна из самых сложных конструкций, которая существует в регулярных выражениях и не поддерживается в JavaScript, и многих других языках программирования.

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

Эта конструкция напоминает тернарный оператор из языков программирования и выглядит следующим образом: /(? ifthen|else)/.

Таблица с википедии
Таблица с википедии

Флаги

В некоторых языках (например, в JavaScript) реализованы т. н. «флаги», которые расширяют функции RegExp. Флаги указываются после регулярного выражения (порядок флагов значения не имеет).По сути это те же модификаторы, но теперь они работают не для отдельной группы, а для всего выражения в целом. Типичные флаги:

g — глобальный поиск (обрабатываются все совпадения с шаблоном поиска);
i — регистр букв не имеет значения;
m — многострочный поиск;
s — текст трактуется как одна строка, в этом случае метасимволу . (точка) соответствует любой одиночный символ, включая символ новой строки;
u — unicode-трактовка. Выражение может содержать специальные паттерны, характерные для юникода, например, /\p{Lu}/ — заглавные буквы.

Флаг указывается после паттерна, например, вот так: /[0-9]$/m.

Выводы

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

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

Советую изучить материалы из раздела «Полезные ссылки», так вы сможете углубить свои знания и закрепить их на деле.

Полезные ссылки

Разобраться с синтаксисом можно на следующих ресурсах:

Другие статьи (более подробные) на эту тему:

Тренажеры: