Когда тянуться к regex
Регулярные выражения — маленький язык для описания текстовых паттернов. Они мощные и легко над-используются.
Прежде чем идти к re, спроси себя, справятся ли обычные методы строк. .split(), .replace(), .startswith(), "target" in text — быстрее, читаемее и менее подвержены ошибкам, чем эквивалентный regex. Оставь regex для случаев, где нужный тебе паттерн действительно структурированный, но слишком гибкий для фиксированных строковых операций: email-ы, номера телефонов, лог-строки с известной формой, HTML или Markdown куски, любой поиск «найди такое-то вот».
Базовый словарь
Regex-паттерн — строка, описывающая то, что ты ищешь. Несколько кирпичиков:
.— любой один символ\d— любая цифра (0–9)\w— любой «словесный» символ (буква, цифра, подчёркивание)\s— любой пробельный символ^— начало строки$— конец строки[abc]— один из a, b или c[^abc]— любой символ, кроме a, b, ca|b— a или b*— ноль или больше предыдущего+— один или больше?— ноль или один{3}— ровно 3{2,5}— от 2 до 5( ... )— группа (захватывает совпадение внутри)
Этого хватит на большинство реальных regex-ов.
Ключевые функции
re.search(pattern, text) находит первое совпадение где угодно в строке. Возвращает match-объект или None:
Всегда используй raw-строку (r"...") для regex-паттернов. Иначе Python попытается интерпретировать обратные слэши как строковые escape-ы, и ты получишь другой паттерн, чем задумывал.
re.match(pattern, text) как search, но совпадает только в начале:
Чаще всего нужен search.
re.findall(pattern, text) возвращает все неперекрывающиеся совпадения списком:
Заметь: findall возвращает строки, а не match-объекты. Если в паттерне одна группа — получишь содержимое группы. Несколько групп — список кортежей.
Захватывающие группы
Скобки в паттерне захватывают то, что совпало внутри:
Именованные группы обычно читаются лучше:
Как только в regex больше одной группы, имена делают код извлечения значительно понятнее.
Замена через re.sub
re.sub(pattern, replacement, text) заменяет каждое совпадение:
Вырезает всё, что не цифра. В замене можно ссылаться на захваченные группы через \1, \2 и так далее, а в raw-строках \g<1> яснее:
В качестве замены можно передать и функцию. Удобно для преобразований, не сводящихся к простому обмену:
Компилируем паттерн для переиспользования
Если ты используешь один и тот же паттерн много раз — особенно в цикле, — скомпилируй его один раз:
У скомпилированных паттернов те же методы — search, match, findall, sub — только без паттерна первым аргументом. Чуть эффективнее и часто читаемее.
Флаги
Типичные модификаторы, передаваемые аргументом flags= или соединяемые через |:
re.IGNORECASE(re.I) — без учёта регистра.re.MULTILINE(re.M) —^и$совпадают на каждой строке, а не только на границах всей строки.re.DOTALL(re.S) —.совпадает и с переводом строки (по умолчанию — нет).re.VERBOSE(re.X) — разрешает пробелы и#-комментарии в паттерне ради читаемости.
re.VERBOSE особенно удобен для сложных паттернов:
Многострочные закомментированные regex-ы поддерживать гораздо проще, чем непрозрачные однострочники.
Жадные vs ленивые
Квантификаторы (*, +, ?, {n,}) по умолчанию жадные — хватают как можно больше. Добавь ?, чтобы сделать их ленивыми:
Жадная версия захватывает всю подстроку от <b> до </i> — скорее всего, не то, чего ты хотел. Ленивый .+? останавливается на первом >.
(Заметка на полях: реальный HTML regex-ом в продакшене не парсят. Используй html.parser или BeautifulSoup. Пример выше — только ради демонстрации жадности.)
Реалистичный пример
Разбор строк простого лога:
Много мощности в немногих строках.
Несколько привычек
- Всегда используй raw-строки для паттернов.
- Начинай с простейшего работающего паттерна; ужесточай потом.
- Именованные группы — как только групп больше одной.
- Компилируй паттерны, которые будешь переиспользовать.
- Regex медленнее обычных методов строк. Если
.split()справится — бери.split().
Дальше: ошибки и отладка
Это закрывает тур по реальным данным — файлам, JSON, CSV, HTTP, датам и regex. В любой реальной программе рано или поздно всплывает ошибка, и умение хорошо читать трейсбэки Python — самый большой отладочный навык, который можно развить. Последняя глава — про исключения и конкретные ошибки, которые встречаются чаще всего.
Часто задаваемые вопросы
Что такое regex в Python?
Регулярное выражение (regex) — это маленький язык для описания паттернов в тексте. Модуль re в Python позволяет искать паттерны, извлекать куски и заменять совпадения. Для простых строковых операций это перебор — сначала бери методы строк вроде .split() или .replace(), — но для структурированного поиска regex вне конкуренции.
В чём разница между re.match и re.search?
re.match ищет совпадение только в начале строки. re.search сканирует всю строку и находит первое совпадение где угодно. Сомневаешься — бери search: он ближе к человеческой интуиции.
Всегда ли использовать raw-строки для regex-паттернов?
Да. В regex-паттернах часто есть обратные слэши (\d, \s, \b), которые Python в обычных строках трактует как escape-последовательности. Префикс r — r'\d+' — говорит Python брать строку буквально, что оставляет сам regex читаемым.