Регулярные выражения: полное руководство для разработчиков
Практическое руководство по регулярным выражениям: базовый синтаксис, группы захвата, lookahead/lookbehind, типичные паттерны и отладка в разных языках программирования.
Регулярные выражения - это инструмент, который разработчики либо любят, либо избегают полностью. Они выглядят устрашающе - плотная строка специальных символов, кажущаяся непостижимой, - но базовая модель проста. Как только вы понимаете, как они работают, хорошо написанное регулярное выражение превращается в один из мощнейших однострочных инструментов во всём вашем арсенале.
Regex TesterTest and debug regular expressions with live matching.Open the tool →Это руководство отсекает лишнее. Вместо перечисления всех возможностей регулярных выражений оно сосредоточено на 20% синтаксиса, покрывающего 80% реальных задач: классы символов, квантификаторы, якоря, группы и флаги. По ходу дела вы можете тестировать каждый пример в Тестере регулярных выражений Toolplash - бесплатно, без регистрации, всё остаётся в браузере.
Что такое регулярное выражение?
Регулярное выражение - это паттерн, описывающий множество строк. Применяя регулярное выражение к тексту, вы спрашиваете: «соответствует ли эта строка моему паттерну?» - или, на практике: «найди все подстроки, соответствующие моему паттерну». Сам паттерн записывается на компактном мини-языке, нативно поддерживаемом большинством языков программирования.
Регулярные выражения полезны всякий раз, когда нужно валидировать ввод (является ли это корректным email-адресом?), извлечь данные (выбрать все URL из блока текста), преобразовать текст (заменить все вхождения паттерна) или разбить строку по сложному разделителю. Они работают в браузере, на сервере, в терминале - везде.
Основной синтаксис: 20%, покрывающие 80% задач
Литеральные символы и точка
Большинство символов в регулярном выражении совпадают сами с собой. Паттерн hello буквально совпадает со строкой «hello». Точка . - единственный универсальный подстановочный символ, совпадающий с любым одним символом, кроме новой строки. Так, h.llo совпадает с «hello», «hallo», «hxllo» и так далее.
Классы символов
Квадратные скобки определяют класс символов - набор, из которого в данной позиции может совпасть любой один символ.
[aeiou]- совпадает с любой гласной[a-z]- совпадает с любой строчной буквой (синтаксис диапазона)[A-Za-z0-9]- совпадает с любым буквенно-цифровым символом[^0-9]-^внутри скобок инвертирует класс; совпадает с чем угодно, кроме цифры
Сокращённые классы охватывают наиболее распространённые случаи: \d - любая цифра (то же, что [0-9]), \w - любой «словесный» символ (буквы, цифры, подчёркивание), \s - любой пробельный символ. Их заглавные обратные - \D, \W, \S - совпадают с противоположным.
Квантификаторы
Квантификаторы управляют количеством повторений предшествующего элемента.
*- ноль или более раз+- один или более раз?- ноль или один раз (делает элемент необязательным){3}- ровно 3 раза{2,5}- от 2 до 5 раз включительно{3,}- 3 или более раз
По умолчанию квантификаторы жадные - они захватывают как можно больше. Добавление ? после квантификатора делает его ленивым: .*? захватывает как можно меньше. Это различие важно при извлечении контента между разделителями.
Якоря
Якоря не совпадают с символами; они совпадают с позициями в строке.
^- начало строки (или начало строки в многострочном режиме)$- конец строки (или конец строки в многострочном режиме)\b- граница слова - позиция между словесным и несловесным символом
Якоря необходимы для валидации. Без них паттерн \d+ совпал бы с цифрами внутри «abc123xyz». С якорями - ^\d+$ - он совпадает только со строками, состоящими исключительно из цифр.
Группы и чередование
Скобки создают захватывающие группы. Они служат двум целям: группировке подвыражения для применения квантификатора ко всей группе и захвату совпавшей подстроки для извлечения.
// Group with quantifier: match one or more "ab" repetitions
/(ab)+/ → matches "ab", "abab", "ababab"
// Alternation with |: match "cat" or "dog"
/(cat|dog)/ → matches "I have a cat" and "I have a dog"
// Named capture group
/(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/Незахватывающие группы - (?:...) - группируют без захвата, что чище, когда нужна только группировка без извлечения совпавшего текста.
Практические примеры
Валидация email
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/Разбор: ^ привязывает к началу. [a-zA-Z0-9._%+-]+ совпадает с локальной частью (один или более допустимых символов). @ - буквальный символ «@». [a-zA-Z0-9.-]+ совпадает с доменным именем. \. - буквальная точка (экранированная, так как неэкранированная . означает «любой символ»). [a-zA-Z]{2,} совпадает с доменом верхнего уровня длиной не менее 2 букв. $ привязывает к концу.
Номер телефона (формат США)
/^+?1?s?((?d{3})?[s.-]?)(d{3}[s.-]?d{4})$/Совпадает с форматами вроде 555-867-5309, (555) 867-5309, +1 555 867 5309 и 5558675309. Ключевой приём - использование ? для необязательных разделителей и группировки кода города с необязательными скобками.
Извлечение URL из текста
/https?://[^s"'<>]+/g
https? совпадает с «http» и «https» (символ s необязателен). :\/\/ совпадает с буквальным «://» с экранированными косыми чертами. [^\s"'<>]+ совпадает со всем, что не является пробелом или типичными завершающими символами URL. Флаг g находит все совпадения, а не только первое.
Флаги регулярных выражений
Флаги изменяют применение всего паттерна.
g(глобальный) - находит все совпадения, а не только первоеi(без учёта регистра) - рассматривает верхний и нижний регистр как эквивалентные;/hello/iсовпадает с «Hello», «HELLO» и «hello»m(многострочный) - заставляет^и$совпадать с началом/концом каждой строки, а не всей строки целикомs(dotAll) - заставляет.также совпадать с символами новой строки, полезно для совпадения через разрывы строк
В JavaScript флаги идут после закрывающей косой черты: /pattern/gi. В Python они передаются вторым аргументом: re.findall(pattern, text, re.IGNORECASE).
JavaScript vs Python: ключевые различия
Синтаксис регулярных выражений в основном одинаков в JavaScript и Python, но есть несколько важных отличий.
- Именованные группы: JavaScript использует
(?<name>...), Python - то же самое. Обе возвращают именованные группы, но доступ к ним различается -match.groups.nameв JS,match.group('name')в Python. - Просмотр вперёд/назад: обе поддерживают
(?=...)(положительный просмотр вперёд) и(?!...)(отрицательный). Python также поддерживает просмотры назад переменной длины; более старые движки JavaScript - нет. - Unicode: JavaScript требует флага
uдля обработки экранирований свойств Unicode вроде\p{Letter}. Модульreв Python обрабатывает Unicode по умолчанию. - Сырые строки: в Python всегда используйте сырые строки (
r"\d+"), чтобы избежать двойного экранирования. В JavaScript используйте либо литеральный синтаксис/\d+/, либо строку"\\d+"при конструировании черезnew RegExp().
Типичные ошибки в регулярных выражениях
- Катастрофический откат - паттерны вроде
(a+)+на несовпадающей строке могут вызвать экспоненциальный откат, блокируя движок. Избегайте вложенных квантификаторов для перекрывающихся паттернов. - Забытое экранирование точки -
3.14как паттерн совпадает с «3X14», потому что.- подстановочный символ. Используйте3\.14для совпадения с буквальной точкой. - Отсутствие якорей в паттернах валидации - без
^и$паттерн, предназначенный для валидации всей строки, совпадёт с любой строкой, содержащей паттерн как подстроку. - Использование регулярных выражений для разбора HTML - регулярные выражения не могут обрабатывать произвольно вложенные структуры. Используйте настоящий HTML-парсер (DOMParser в браузере, BeautifulSoup в Python) для разбора HTML.
Тестируйте паттерны безопасно в браузере
Писать регулярные выражения в редакторе без обратной связи - мучение. Написали паттерн, запустили код, увидели ошибку, поправили паттерн, запустили снова. Живой тестер регулярных выражений замыкает этот цикл - вы видите совпадения, подсвеченные в реальном времени по мере ввода.
Тестер регулярных выражений Toolplash позволяет написать паттерн, вставить тестовые строки и мгновенно увидеть все совпадения подсвеченными. Он работает полностью в браузере, так что вы можете тестировать на реальных данных - логах, пользовательском вводе, production-строках - без отправки чего-либо на сервер.
Итоги
Регулярные выражения окупают вложенное в их изучение время. Базовый словарь - классы символов, квантификаторы, якоря, группы и флаги - невелик. Паттерны, которые можно на его основе строить, - безграничны. Начните с примеров из этого руководства, тестируйте их на собственных строках, и синтаксис станет интуитивным быстрее, чем вы ожидаете.
Regex TesterTest and debug regular expressions with live matching.Open the tool →Try the Tools - 100% Free, No Sign-Up
Everything runs in your browser. No uploads. No accounts. No ads.
Explore All Tools →