Регулярные выражения в Python: полный набор символов и их использование
Основные символы регулярных выражений Python
Регулярные выражения (regex) в Python реализованы в модуле re. Каждый символ в шаблоне может быть либо обычным (ищет себя), либо специальным (метасимволом). Основной подход - использовать сырые строки (r'...'), чтобы избежать двойного экранирования.
Цель: быстро и гибко искать, заменять или проверять строки по шаблону.
Пример базового шаблона: поиск цифр в строке.
import re
text = "Цена 250 рублей, скидка 10%"
pattern = r'\d+'
match = re.search(pattern, text)
if match:
print(match.group()) # 250любой символ python (любой символ в регулярных выражениях python)
250
Python re match (регулярное выражение re.match в python)
Здесь \d - сокращённый класс для любой цифры, + - квантификатор «одно или более вхождений». Без сырой строки пришлось бы писать '\\d+'.
Типичная ошибка: забыть сырую строку - тогда обратная косая черта воспринимается как экранирование в Python. Решение: всегда используйте r'' для regex.
Как задать любой символ с помощью точки (.)
Метасимвол . соответствует любому одиночному символу, кроме символа новой строки (\n).
import re
print(re.findall(r'т.ст', 'текст, тест, ткст'))
символы регулярных выражений python (символы регулярных выражений python)
['тест', 'ткст']
Шаблон т.ст найдёт слова, где между «т» и «ст» стоит один символ.
Проблема: точка не совпадает с переводом строки. Если нужно совпадение с любым символом, включая \n, используйте флаг re.DOTALL.
Как использовать квантификаторы для повторения символов
Квантификаторы управляют количеством повторений предыдущего элемента.
- * - ноль или больше
- + - один или больше
- ? - ноль или один
- {m,n} - от m до n включительно
import re
print(re.findall(r'\d{2,4}', '12 123 12345 1'))
['12', '123', '1234']
Шаблон \d{2,4} находит последовательности из 2–4 цифр.
Ошибка: пересечение совпадений - по умолчанию квантификаторы «жадные». Если нужно минимальное совпадение, добавьте ? после квантификатора (например, *?, +?).
Как задать набор символов с помощью квадратных скобок [ ]
Внутри скобок перечисляются допустимые символы или диапазоны (a-z, 0-9). Символ ^ в начале набора инвертирует его.
import re
print(re.findall(r'[аеёиоуыэюя]', 'Привет, как дела?'))
['и', 'е', 'а', 'е', 'а']
Шаблон ищет все гласные буквы русского алфавита.
Важно: большинство метасимволов внутри [...] теряют своё специальное значение (кроме \, ^, - и ]). Не экранируйте без необходимости.
Как использовать якоря начала и конца строки
^ - начало строки, $ - конец строки. Они не захватывают символы, а указывают позицию.
import re
print(bool(re.search(r'^Привет', 'Привет, мир!'))) # True
print(bool(re.search(r'мир!$', 'Привет, мир!'))) # True
True True
С флагом re.MULTILINE ^ и $ совпадают с началом/концом каждой строки.
Ошибка: забыть, что ^ внутри [...] меняет смысл на отрицание.
Как создавать группы и обратные ссылки
Круглые скобки ( ) создают группу, которую можно извлечь или использовать в обратной ссылке (\1, \2 и т.д.).
import re
match = re.search(r'(\w+)@(\w+)\.(\w+)', 'user@example.com')
if match:
print(match.group(1), match.group(2)) # user example
user example
Группы также можно именовать: (?P<name>...).
Проблема: нумерация групп начинается с 1, а group(0) возвращает всё совпадение. При использовании обратных ссылок в шаблоне требуется экранирование: \\1 в обычной строке или r'\1'.
Как экранировать специальные символы
Чтобы использовать метасимвол как обычный, перед ним ставится обратная косая черта: \., \*, \+.
import re
print(re.findall(r'\.', 'точка.ещё.точка'))
['.', '.']
Типичная ошибка: неверное количество обратных косых черт. В сырой строке r'\.' - одна косая для regex. В обычной строке пришлось бы писать '\\.'.
Как использовать сокращенные классы символов
Python предоставляет сокращения для популярных наборов:
- \d - цифра (аналог [0-9])
- \w - буква, цифра, подчёркивание (аналог [a-zA-Z0-9_] для латиницы)
- \s - пробельный символ (пробел, табуляция, перевод строки)
- \D, \W, \S - инверсия
import re
print(re.findall(r'\w+', 'Python 3.11 - мощный язык!'))
['Python', '3', '11', 'мощный', 'язык']
Примечание: \w не включает русские буквы по умолчанию; для их учёта используйте флаг re.ASCII (отключает юникод) или явные диапазоны [а-яА-ЯёЁ].
Как использовать флаги (re.IGNORECASE, re.MULTILINE и другие)
Флаги изменяют поведение regex. Передаются вторым аргументом в функции или в шаблоне через (?i).
import re
text = "Python\npython\nPYTHON"
print(re.findall(r'^python', text, re.IGNORECASE | re.MULTILINE))
['Python', 'python', 'PYTHON']
Без re.MULTILINE ^ совпал бы только в начале всей строки.
Ошибка: забыть комбинировать флаги через побитовое ИЛИ (|). Также флаг re.UNICODE включён по умолчанию; re.ASCII отключает его.
Расширенные примеры использования символов регулярных выражений
1. Lookahead и lookbehind (опережающая и ретроспективная проверка)
Эти конструкции не захватывают символы, а только проверяют условие.
- (?=...) - положительный lookahead: совпадение, если после текущей позиции следует ...
- (?!...) - отрицательный lookahead
- (?<=...) - положительный lookbehind (только фиксированной длины)
- (?<!...) - отрицательный lookbehind
import re
# Найти слово, после которого идёт '!' без восклицательного знака в результате
text = "Привет! Как дела? Пока!"
print(re.findall(r'\w+(?=!)', text))
['Привет', 'Пока']
# Найти слово, перед которым стоит 'Как '
print(re.findall(r'(?<=Как )\w+', text))
['дела?']
Особенность: lookbehind не поддерживает квантификаторы с неопределённой длиной (*, +).
2. Нежадные (ленивые) квантификаторы
По умолчанию квантификаторы жадные - захватывают максимально длинную строку. Добавление ? делает их ленивыми.
import re
html = "<div>текст</div><div>ещё</div>"
# Жадный:
print(re.findall(r'<div>.*</div>', html))
# Ленивый:
print(re.findall(r'<div>.*?</div>', html))
['<div>текст</div><div>ещё</div>'] ['<div>текст</div>', '<div>ещё</div>']
3. Pattern с комментариями (re.VERBOSE)
Флаг re.VERBOSE (или re.X) позволяет писать шаблон в несколько строк, игнорируя пробелы и добавляя комментарии с #.
import re
pattern = re.compile(r'''
\b # граница слова
\d{2,4} # от 2 до 4 цифр
\s? # необязательный пробел
[а-яА-Я]+ # хотя бы одна русская буква
\b
''', re.VERBOSE | re.IGNORECASE)
print(pattern.findall('75 лет 1234 года 5 лет'))
['75 лет', '1234 года']
Пробелы в шаблоне игнорируются, поэтому количество лет «5» не совпало (одна цифра).
4. Использование границы слова \b
\b совпадает на стыке символа слова (\w) и не-слова. Полезно для поиска целых слов.
import re
print(re.findall(r'\bкот\b', 'кот, котёнок, котик'))
['кот']
Без \b нашлись бы все вхождения «кот», включая части других слов.
5. Атомарные группы и possessive квантификаторы
В Python нет встроенных атомарных групп, но можно эмулировать с помощью (?>...) - такая группа не отдаёт символы обратно при backtracking. Начиная с Python 3.11 поддерживается (?>...).
import re
# Пример без атомарной группы - backtracking приводит к совпадению
print(re.search(r'a(?:bc|b)c', 'abcc')) # совпадёт 'abcc'
# С атомарной группой - после выбора bc группа не перебирает b
print(re.search(r'a(?>bc|b)c', 'abcc')) # не совпадёт, потому что bc уже захвачено, c не хватает
<re.Match object; span=(0,4), match='abcc'> None
Это предотвращает ненужный перебор вариантов и ускоряет поиск.
6. Условные шаблоны (if-then-else)
Конструкция (?(id/name)yes_pattern|no_pattern) позволяет сопоставлять разные шаблоны в зависимости от того, была ли найдена группа.
import re
# Если есть префикс 'tel:', то после него ищем номер из 10 цифр, иначе - произвольный номер
pattern = r'(tel:)?(?(1)\d{10}|\d{7})'
tests = ['tel:1234567890', '1234567', 'tel:12345']
for t in tests:
m = re.search(pattern, t)
print(t, '->', m.group() if m else None)
tel:1234567890 -> 1234567890 1234567 -> 1234567 tel:12345 -> None
7. Обработка Unicode с помощью \p{...} (Python 3.8+ модуль regex)
Стандартный модуль re не поддерживает \p{...}, но сторонний модуль regex даёт юникодные категории. Если он установлен:
import regex
print(regex.findall(r'\p{Lu}+', 'Привет Мир')) # заглавные буквы
['П', 'М']
Для стандартного re можно использовать [\u0400-\u04FF].
8. Пересечение и исключение в символьных классах (модуль regex)
Модуль regex поддерживает операторы && (пересечение) и -- (вычитание).
import regex
# Все латинские буквы, кроме гласных
print(regex.findall(r'[a-z&&[^aeiou]]+', 'hello world'))
['hll', 'wrld']