Найти в Дзене
Kenu Len

Регулярные выражения. Часть 3: Необычные операции

Мы прошли основы, познакомились с проверками, теперь можно опробовать и более интересные возможности регулярных выражений. Игнорирование Возьмём строки: Допустим, мы решили выделить слово "кошка" с конкретными окончаниями -"ка" и "ечка". Регулярное выражение будет следующим: .+\s(кош(ка|ечка)), где: Как видим, помимо слов с нужными окончаниями, в группы выделяются и сами окончания. Чтобы этого избежать, воспользуемся специальным ключом - (?:) ?: сигнализирует о том, что группу не следует захватывать как отдельный результат. Обращение к группе по имени В первой статье упоминалось о том, что группе можно назначить имя, но самое интересное, что по этому имени можно обратиться внутри регулярного выражения! Синтаксис (?&ИМЯ_ГРУППЫ). Это жуть какая удобная вещь при работе с крупными регулярными выражениями, так как изменение номера группы - обычное дело! Вести подсчет и каждый раз вносить правки становится неловкой рутиной. Работа с именами и обращение по ним снимает с нас эту головную бол
Оглавление

Мы прошли основы, познакомились с проверками, теперь можно опробовать и более интересные возможности регулярных выражений.

Игнорирование

Возьмём строки:

  • шла кошка;
  • шли кошки;
  • шла кошечка.

Допустим, мы решили выделить слово "кошка" с конкретными окончаниями -"ка" и "ечка". Регулярное выражение будет следующим:

.+\s(кош(ка|ечка)), где:

  • .+- повторение любого символа;
  • \s - один пробельный символ;

Как видим, помимо слов с нужными окончаниями, в группы выделяются и сами окончания. Чтобы этого избежать, воспользуемся специальным ключом - (?:)

-2

?: сигнализирует о том, что группу не следует захватывать как отдельный результат.

Обращение к группе по имени

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

Синтаксис (?&ИМЯ_ГРУППЫ). Это жуть какая удобная вещь при работе с крупными регулярными выражениями, так как изменение номера группы - обычное дело! Вести подсчет и каждый раз вносить правки становится неловкой рутиной. Работа с именами и обращение по ним снимает с нас эту головную боль.

-3

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

  • Определили группу G1, содержащую последовательность от 1 до бесконечности символов;
  • Определили G2 внутри которой ищем \w+ = \w+;. Однако теперь мы можем не переписывать выражение \w+, а обращаться по имени группы - (?&G1).

Рекурсия

Может показаться странным, но... Да. Вы можете создать рекурсию. Итак, перейдем к задаче, на которой её можно хорошо продемонстрировать! У нас есть две функции, написанные на языке программирования Си (правда мы рассматриваем псевдокод, нас интересуют только фигурные скобки):

функции func_1 и func_2
функции func_1 и func_2

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

  • \w+ - тип возвращаемого значения;
  • \s+ - хотя бы один пробел;
  • \w+ - имя функции;
  • \( \) - скобки (\ для экранирования спецсимвола, без него скобки будут считаться границами группы);
  • { - открывающая фигурная скобка.
  • [\w\s;()]* - любое количество символов и пробелов перечисленных в квадратных скобках.

Отлично, мы захватили часть тела функции!

-5

Осталось в квадратные скобки включить фигурные и все:

  • [\w\s;(){}]* - любое количество символов и пробелов перечисленных в квадратных скобках.
-6

Не тут то было! Теперь результат записывается сплошным текстом, а добавление крайних фигурных скобок в выражение ситуацию не исправляет:

-7

Тут то на помощь и приходит рекурсия! Слегка изменим наше выражение:

-8

Что здесь случилось? Рекурсия! А реализует ее короткая запись (?1)*, она говорит, что на ее месте может быть от 0 до бесконечности повторений группы 1 ( [\s\w;()]*{[\s\w;()]*} ). Это последовательность {} {}. Так как группа 1 хранит внутри себя поиск той же группы 1, то и последовательность {{{}}} будет попадать под наш прицел! Добавление рекурсии позволило четко определить открывающую и закрывающую фигурные скобки как границы тел двух функций.

Советую вам самим поиграться на упрощённой версии:

-9

К слову, можно обойтись и без скобок, регулярное выражение целиком имеет номер 0, либо можно обратиться по ключу R - (?R)* или (?0)*

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

-10

Теперь, при добавлении групп "тип функции" или "имя функции" и т.д. не придется следить за номером группы и постоянно корректировать регулярное выражение! Уверяю, вам это сэкономить уйму нервов :)

Полный плейлист