Добавить в корзинуПозвонить
Найти в Дзене

Регулярные выражения. Скобочные группы и проверки

📌 Больше полезных статей по информатике и программированию вы можете найти у нас на сайте. 📢 Следить за новостями мира информатики, а также общаться, делиться впечатлениями и готовиться к экзаменам лучше вместе, в нашем Telegram-канале. Это заключительная статья из цикла про регулярные выражения. Здесь мы изучим работу скобочных групп и научимся использовать опережающие и ретроспективные проверки в регулярных выражениях. Остальные доступны по ссылкам ниже: Скобочные группы в регулярных выражениях в Python используются для группировки частей шаблона и извлечения соответствующих подстрок. Это полезно для применения квантификаторов к части выражения, захвата подстрок для дальнейшего использования и более сложного поиска. Группы обозначаются круглыми скобками «(…)» и имеют такой же смысл, как в математических выражениях. Например, шаблону «(\d+)-(\d+)» будут соответствовать подстроки формата «<одна и более цифра>-<одна и более цифра>». Если в шаблоне есть группирующие скобки, то функцией
Оглавление

📌 Больше полезных статей по информатике и программированию вы можете найти у нас на сайте.

📢 Следить за новостями мира информатики, а также общаться, делиться впечатлениями и готовиться к экзаменам лучше вместе, в нашем Telegram-канале.

Это заключительная статья из цикла про регулярные выражения. Здесь мы изучим работу скобочных групп и научимся использовать опережающие и ретроспективные проверки в регулярных выражениях.

Остальные доступны по ссылкам ниже:

Скобочные группы

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

Группы обозначаются круглыми скобками «(…)» и имеют такой же смысл, как в математических выражениях.

Например, шаблону «(\d+)-(\d+)» будут соответствовать подстроки формата «<одна и более цифра>-<одна и более цифра>».

Если в шаблоне есть группирующие скобки, то функцией findall() вместо списка найденных подстрок будет возвращён список кортежей, в каждом из которых будет строка, соответствующая каждой группе.

-2

Также сформированные группы можно вызвать методами group() и groops() match-объекта, например, при использовании функции search():

-3

Скобочные выражения группируют вместе части регулярного выражения, и к каждой группе может быть применен квантификатор. К примеру, составим шаблон для определения телефонного номера вида: «12-34-56». То есть у нас есть группа, где любая цифра повторяется 2 раза, далее идет дефис и снова повторяется эта группа, и так еще один раз.

Можем составить такую программу для извлечения телефонного номера из строки:

-4

Давайте подробней разберем работу с группами на следующем примере. Допустим, нам необходимо найти подстроку формата «<текст> = <число>», которую с обеих сторон может окружать любое количество пробельных символов.

Тогда шаблон будет состоять из следующих частей:

  1. Символы «\s*» для определения любого количества пробельных символов в начале строки.
  2. Первая группа «([a-zA-Z]+)», которая определяет 1 и более латинских букв подряд.
  3. Символ «=».
  4. Вторая группа «(\d+)», которая определяет 1 и более цифр.
  5. Символы «\s*» для определения любого количества пробельных символов в конце строки.

Напишем такую программу:

-5

Все захваченные группы и их индексы проиллюстрированы на изображении ниже.

-6

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

Но бывают ситуации, когда все же нужно использовать группу для сбора части регулярного выражения, но вы не заинтересованы в извлечении содержимого группы и не планируете далее работать с методами group() и groups(). В таком случае можно использовать группы без захвата содержимого.

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

Давайте сравним работу обеих групп. В следующем примере первая группа будет без захвата, а вторая – с захватом содержимого:

-7

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

Позиционные проверки

Позиционные проверки в регулярных выражениях — это специальные конструкции, которые позволяют проверять положение символов в строке, не захватывая их.

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

Различают опережающие и ретроспективные проверки.

Опережающие проверки

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

Опережающие проверки бывают положительными и отрицательными:

  1. Положительные опережающие проверки «(?=…)»
  2. Отрицательные опережающие проверки «(?!…)»

Положительные опережающие проверки проверяют, что за текущей позицией в строке следует подстрока, соответствующая шаблону внутри «(?=)», но не захватывают её в результатах.

Для примера давайте найдём подстроку максимальной длины (выделена зелёным), после которой находятся символы «cba» (выделены оранжевым) в строке «abcabccbabaccab».

-8
-9

В случае с отрицательными опережающими проверками всё наоборот. Они проверяются, что за текущей позицией в строке не следует подстрока, соответствующая шаблону внутри «(?!)».

Например, выберем все буквы A, после которых не следует буква C:

-10

Ретроспективные проверки

Теперь перейдём к ретроспективным проверкам. Ретроспективная проверка (lookbehind assertion) позволяет проверить, что перед текущим шаблоном находится (или не находится) определённый текст, без включения этого текста в результат.

Так же, как и опережающие, ретроспективные проверки делятся на положительные и отрицательные.

Положительные ретроспективные проверки «(?<=…)» проверяют, что перед текущей позицией в строке существует подстрока, соответствующая шаблону внутри «(?<=)», но не захватывают её в результатах.

Обратите внимание, что ретроспективные проверки должны иметь фиксированную длину. Шаблоны переменной длины (например, с использованием квантификаторов) в ретроспективных проверках не поддерживаются.

Давайте теперь найдём максимальную подстроку, перед которой находятся символы «cba» во все той же строке: «abcabccbabaccab»

-11
-12

Отрицательные же ретроспективные проверки проверяют, что перед текущей позицией в строке не существует подстрока, соответствующая шаблону внутри «(?<!)».

Немного усложним наши примеры. У нас есть строка, состоящая из пар символов: «AB AC DC BB CA AD». Нужно вывести вторую букву (выделены зелёным) только тех пар, которые не начинаются с А (выделены оранжевым).

-13

В коде это будет выглядеть так:

-14

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

-15