Обратные ссылки и альтернация |

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

Обратная ссылка \1 требует, чтобы в этом месте повторился тот же текст, что захватила группа 1.

Альтернация: «или»

Оператор | означает «или» — совпадёт любой из вариантов. Паттерн кот|пёс|рыбка найдёт любое из трёх слов:

import re

print(re.findall(r"кот|пёс|рыбка", "у меня кот и пёс"))

Вывод:

['кот', 'пёс']

Группировка альтернатив

Альтернация по умолчанию «растягивается» до краёв паттерна. Часто это не то, что нужно. Чтобы ограничить выбор, его берут в скобки. Сравните: gr(a|e)y — это «gr», потом «a или e», потом «y»:

import re

print(re.findall(r"\b(cat|dog)s?\b", "cat dogs cats dog"))

Вывод:

['cat', 'dog', 'cat', 'dog']

Здесь (cat|dog) — выбор слова, s? — необязательное множественное число, а \b по краям — границы слова. findall вернул содержимое группы для каждого совпадения. Без скобок \bcat|dogs?\b читалось бы движком совсем иначе — скобки важны.

Обратные ссылки: повтор того же текста

Захваченную группу можно переиспользовать внутри того же паттерна через \1, \2 и т.д. Это требует, чтобы дальше встретился ровно такой же текст. Найдём задвоенные слова:

import re

text = "the the cat sat sat down"
print(re.findall(r"\b(\w+) \1\b", text))

Вывод:

['the', 'sat']

Паттерн (\w+) \1 читается так: захватили слово в группу 1, затем пробел, затем \1 — то же самое слово ещё раз. Так находят опечатки-дубли «the the».

Обратные ссылки в парных тегах

Другой пример — найти HTML-тег, у которого открывающее и закрывающее имена совпадают:

import re

html = "<b>жирный</b> и <i>курсив</i>"
print(re.findall(r"<(\w+)>.*?</\1>", html))

Вывод:

['b', 'i']

Группа 1 ловит имя тега, а \1 требует то же имя в закрывающем теге. Так совпадут только корректно закрытые пары. (Но честно парсить HTML регулярками всё равно не стоит — об этом в последнем разделе.)

Итог

  • | — альтернация «или»; ограничивайте её скобками: (cat|dog).
  • findall с группами возвращает содержимое групп, а не всё совпадение.
  • Обратные ссылки \1, \2 требуют повтора текста, захваченного группой; полезны для поиска дублей и парных тегов.
Проверьте себя
1. Что означает оператор | в регулярке cat|dog?
AСовпадение и cat, и dog подряд
BАльтернацию: совпадает cat ИЛИ dog
CЛогическое И
DКонец паттерна
2. Что требует обратная ссылка \1 в паттерне (\w+) \1?
AЧтобы дальше шла любая буква
BЧтобы повторился ровно тот же текст, что захватила группа 1
CЧтобы группа была пустой
DЧтобы группа повторилась один или более раз
3. Зачем альтернацию обычно берут в скобки, как в (cat|dog)s?
AСкобки обязательны для любого |
BЧтобы ограничить область выбора и применить к ней общий квантор/границы
CЧтобы ускорить выполнение
DЧтобы сделать поиск регистронезависимым
Поддержать проект