Модуль re — регулярные выражения в Python
Регулярные выражения (regex, regexp) — это маленький язык для описания шаблонов в тексте. С их помощью можно найти e-mail в логе, выдернуть номер телефона из строки, проверить пароль на правила, разобрать формат файла. Это один из самых универсальных инструментов в любом современном языке программирования.
В Python для работы с regex есть стандартный модуль re:
import re
Первый пример
import re
text = 'Сегодня 14 мая 2026 года, температура 23 градуса.'
numbers = re.findall(r'\d+', text)
print(numbers)
# ['14', '2026', '23']
\d+ — это шаблон: «одна или больше цифр подряд». Модуль прошёл по строке и
вернул все совпадения.
Совет
Регулярки пишут с префиксом r'' (raw-string). Иначе обратные слэши
\d, \w, \s придётся удваивать.
Основные конструкции
. любой символ кроме переноса строки
\d цифра 0-9 \D не цифра
\w буква/цифра/_ \W не буква/цифра
\s пробел/таб/перенос \S не пробел
^ начало строки
$ конец строки
* 0 и более повторений предыдущего
+ 1 и более повторений
? 0 или 1 (опционально)
{n} ровно n повторений
{n,m} от n до m повторений
[abc] один из перечисленных символов
[a-z] диапазон
[^abc] любой кроме перечисленных
| или (apple|banana)
() группа
\b граница слова
Основные функции модуля re
re.match(pat, s)— проверяет совпадение в начале строки.re.search(pat, s)— ищет первое совпадение в любом месте.re.findall(pat, s)— возвращает список всех совпадений.re.finditer(pat, s)— то же, но итератором (с объектами Match).re.sub(pat, repl, s)— заменяет совпадения.re.split(pat, s)— режет строку по шаблону.re.fullmatch(pat, s)— проверяет, что вся строка соответствует шаблону.
Пример: проверка e-mail
import re
pattern = r'^[\w.+-]+@[\w-]+\.[\w.-]+$'
def is_email(s):
return re.match(pattern, s) is not None
print(is_email('user@example.com')) # True
print(is_email('user@@example.com')) # False
print(is_email('просто текст')) # False
Это упрощённый шаблон — настоящая RFC-валидная регулярка для e-mail монструозна. Для большинства задач хватает простой проверки.
Группы и захват
Скобки () создают группу — кусок, который можно «вынуть» отдельно.
import re
text = 'Сегодня 14.05.2026'
m = re.search(r'(\d{2})\.(\d{2})\.(\d{4})', text)
if m:
day, month, year = m.groups()
print(year, month, day)
# 2026 05 14
Именованные группы делают код понятнее:
m = re.search(r'(?P<day>\d{2})\.(?P<month>\d{2})\.(?P<year>\d{4})', text)
print(m['year']) # 2026
print(m['day']) # 14
Замена с группами: re.sub
import re
text = 'Дата: 14.05.2026'
result = re.sub(r'(\d{2})\.(\d{2})\.(\d{4})', r'\3-\2-\1', text)
print(result)
# Дата: 2026-05-14
В строке замены \1, \2, \3 ссылаются на захваченные группы.
Флаги
re.IGNORECASE(re.I) — игнорировать регистр.re.MULTILINE(re.M) —^и$совпадают с началом/концом каждой строки, а не всего текста.re.DOTALL(re.S) —.начинает совпадать и с переносом строки.re.VERBOSE(re.X) — разрешает пробелы и комментарии внутри шаблона.
import re
text = 'Python и PYTHON и pYtHoN'
print(re.findall(r'python', text, re.IGNORECASE))
# ['Python', 'PYTHON', 'pYtHoN']
Флаг VERBOSE для длинных шаблонов:
phone_pattern = re.compile(r'''
\+? # необязательный плюс
(\d{1,3}) # код страны
[\s\-]? # разделитель
\(?(\d{3})\)? # код города
[\s\-]?
(\d{3}) # 3 цифры
[\s\-]?
(\d{2}) # 2 цифры
[\s\-]?
(\d{2}) # 2 цифры
''', re.VERBOSE)
Компиляция шаблона
Если один и тот же шаблон используется много раз, скомпилируйте его заранее — это быстрее:
import re
PHONE = re.compile(r'\+?\d{1,3}\s?\(?\d{3}\)?\s?\d{3}-?\d{2}-?\d{2}')
for line in lines:
if PHONE.search(line):
print('Нашёл телефон:', line)
Практический пример: парсинг логов
Допустим, у нас типичный лог:
2026-05-14 10:23:45 [INFO] User 42 logged in
2026-05-14 10:24:01 [ERROR] Connection refused
2026-05-14 10:24:18 [INFO] User 7 logged out
Распарсим в словари:
import re
LOG = re.compile(r'''
(?P<date>\d{4}-\d{2}-\d{2})\s+
(?P<time>\d{2}:\d{2}:\d{2})\s+
\[(?P<level>\w+)\]\s+
(?P<message>.+)
''', re.VERBOSE)
with open('app.log', encoding='utf-8') as f:
for line in f:
m = LOG.match(line)
if m:
print(m.groupdict())
Жадные и ленивые квантификаторы
По умолчанию +, * и {n,} жадные — стараются захватить как можно
больше. Добавьте ? после квантификатора, чтобы сделать его ленивым:
import re
html = '<b>привет</b> <i>мир</i>'
print(re.findall(r'<.+>', html)) # ['<b>привет</b> <i>мир</i>'] — жадно
print(re.findall(r'<.+?>', html)) # ['<b>', '</b>', '<i>', '</i>'] — лениво
Подводные камни
Предупреждение
``re.match`` не ищет в середине! Он проверяет только начало. Чтобы искать везде —
re.search.HTML/XML регулярками не парсят. Используйте
html.parser,BeautifulSoupилиlxml. Regex не понимает вложенность.Жадность.
.+съест больше, чем вы ожидаете. Думайте, не нужна ли ленивая форма.+?.Производительность. Для огромных текстов плохо составленный regex может работать секундами. Компилируйте шаблоны, избегайте вложенных
*внутри*.Юникод. В Python 3
\wпо умолчанию матчит и кириллицу. Если нужно только латиницу — используйте[A-Za-z0-9_].
Смотрите также
Python: строки — методы строк
Работа с файлами Python — работа с файлами
Примечание
Лицензия и источники
Часть материала адаптирована из официальной документации Python (https://docs.python.org/3/library/re.html и https://docs.python.org/3/howto/regex.html), доступной под Python Software Foundation License Version 2 (PSF License). Адаптация, переработка, оригинальные примеры и пояснения — © AlashEd Wiki.