Regex в Python: шпаргалка

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

Основные функции модуля re

import re

re.search(pattern, string)    # найти первое совпадение
re.findall(pattern, string)   # все совпадения → список
re.finditer(pattern, string)  # все → итератор Match-объектов
re.match(pattern, string)     # только в начале строки
re.fullmatch(pattern, string) # только если вся строка совпадает
re.sub(pattern, repl, string) # замена
re.split(pattern, string)     # разделить по паттерну
re.compile(pattern)           # предкомпилировать для переиспользования

Метасимволы

Символ Что делает
. любой символ кроме \n
^ начало строки
$ конец строки
\\d цифра [0-9]
\\D не-цифра
\\s пробельный символ
\\S не-пробельный
\\w [A-Za-z0-9_]
\\W не \w
\\b граница слова
\\B не граница слова
[abc] любой из a, b, c
[^abc] любой кроме a, b, c
[a-z] любой в диапазоне

Квантификаторы

Значение
* 0 или больше
+ 1 или больше
? 0 или 1
{n} ровно n
{n,} n или больше
{n,m} от n до m

По умолчанию жадные (максимум). *?, +? — ленивые (минимум).

1. Найти email

pattern = r'\b[\w.-]+@[\w.-]+\.\w+\b'
text = "Пиши на alice@example.com или bob@company.ru"
emails = re.findall(pattern, text)
# ['alice@example.com', 'bob@company.ru']

2. Найти номер телефона (РФ)

pattern = r'(?:\+7|8)[\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}'
text = "+7 (495) 123-45-67 или 8 900 111 22 33"
phones = re.findall(pattern, text)

3. Извлечь цифры из строки

text = "Заказ #12345 на 999 рублей"
digits = re.findall(r'\d+', text)
# ['12345', '999']

4. Удалить не-буквы

text = "Привет! Как 123 дела?"
clean = re.sub(r'[^\w\s]', '', text)
# 'Привет Как 123 дела'

5. Заменить на другую строку

text = "Цена 100 рублей, скидка 10 рублей"
result = re.sub(r'\d+ рублей', 'XXX руб.', text)
# 'Цена XXX руб., скидка XXX руб.'

6. Группы через скобки

text = "Иванов Иван Иванович"
m = re.search(r'(\w+)\s+(\w+)\s+(\w+)', text)
m.group(0)  # 'Иванов Иван Иванович' (вся совпавшая часть)
m.group(1)  # 'Иванов'
m.group(2)  # 'Иван'
m.group(3)  # 'Иванович'
m.groups()  # ('Иванов', 'Иван', 'Иванович')

7. Именованные группы

pattern = r'(?P<name>\w+)\s+(?P<age>\d+)'
m = re.search(pattern, "Alice 30")
m.group('name')  # 'Alice'
m.group('age')   # '30'
m.groupdict()    # {'name': 'Alice', 'age': '30'}

8. Извлечь дату в разных форматах

pattern = r'(\d{2})[./-](\d{2})[./-](\d{4})'
dates = re.findall(pattern, "Было 12.04.2026, стало 21/04/2026, позже 15-05-2026")
# [('12', '04', '2026'), ('21', '04', '2026'), ('15', '05', '2026')]

9. Извлечь UTM-параметры из URL

url = "https://example.com?utm_source=google&utm_medium=cpc&ref=abc"
utm = re.findall(r'utm_(\w+)=([^&]+)', url)
# [('source', 'google'), ('medium', 'cpc')]

10. Split по нескольким разделителям

text = "a,b;c.d|e"
parts = re.split(r'[,;.|]', text)
# ['a', 'b', 'c', 'd', 'e']

11. Флаги

# игнорировать регистр
re.findall(r'hello', text, flags=re.IGNORECASE)

# многострочный (^ и $ работают для каждой строки)
re.findall(r'^\w+', text, flags=re.MULTILINE)

# . будет матчить и \n
re.findall(r'<div>.*?</div>', html, flags=re.DOTALL)

# комбинировать через |
re.findall(r'\bhello\b', text, flags=re.I | re.M)

12. Lookahead / Lookbehind

# перед совпадением: (?<=...)
# после совпадения:  (?=...)
# отрицательные: (?<!...) и (?!...)

# цена без валюты
re.findall(r'(?<=цена )\d+', "цена 100, скидка 20")
# ['100']

# число перед рублями
re.findall(r'\d+(?= руб)', "100 руб, 50 долл")
# ['100']

13. Применение в pandas

import pandas as pd

df = pd.DataFrame({'text': ['Заказ #12345', 'Счёт #7890']})

# извлечь число
df['order_id'] = df['text'].str.extract(r'#(\d+)')

# заменить
df['text_clean'] = df['text'].str.replace(r'#\d+', 'ORDER', regex=True)

# проверить, содержит ли паттерн
df['has_order'] = df['text'].str.contains(r'#\d+', regex=True)

14. Предкомпилировать для скорости

# если используете одно и то же regex много раз
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')

for text in texts:
    if pattern.search(text):
        ...

Предкомпиляция ускоряет повторные вызовы в 2-3 раза.

Частые ошибки

Ошибка 1. Забыть raw string

# плохо — \d трактуется как escape-последовательность
re.findall('\d+', text)  # предупреждение в новых Python

# правильно
re.findall(r'\d+', text)

Всегда используйте r'...' для regex.

Ошибка 2. Жадность там, где не нужна

# жадный — захватит максимум
re.findall(r'<.*>', '<a><b>')  # ['<a><b>']

# ленивый — минимум
re.findall(r'<.*?>', '<a><b>')  # ['<a>', '<b>']

Ошибка 3. Не проверять None

m = re.search(pattern, text)
# если нет совпадения, m = None
value = m.group(1)  # AttributeError

# правильно
if m:
    value = m.group(1)

Ошибка 4. Использовать regex для HTML / JSON

Не пользуйтесь regex для HTML — используйте BeautifulSoup. Для JSON — json.loads. Regex плохо справляется с вложенностью.

Связанные темы

FAQ

Что такое raw string и зачем он?

r'...' отключает обработку escape-последовательностей. В regex часто встречается \, и без raw-строки Python пытается интерпретировать \d, \s как escape — некорректно.

search vs match vs fullmatch?

match — только в начале строки. fullmatch — вся строка целиком. search — в любом месте.

Когда use re.compile?

Когда паттерн используется много раз в цикле. Иначе — обычной функцией re.findall/search достаточно.

Как запомнить метасимволы?

Мнемоника: \digit (цифра), \space (пробел), \word (слово), \boundary (граница). Заглавные — отрицание.


Тренируйте Python — откройте тренажёр с 1500+ вопросами для собесов аналитиков.