Regex: менее страшно, чем выглядит
Регулярные выражения имеют репутацию нечитаемых. Но они не обязаны быть такими.
Тебе нужно найти все email-адреса в документе. Или валидировать телефонные номера. Или извлечь даты из грязного текста.
Кто-то говорит "используй regex". Ты гуглишь синтаксис, находишь что-то вроде ^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$, и немедленно закрываешь вкладку.
Регулярные выражения выглядят пугающе, потому что люди пишут их чтобы быть умными, а не понятными. Давай исправим это.
Начни с буквального совпадения
Regex находит паттерны. Простейший паттерн — буквальный текст.
cat совпадает с "cat" в "The cat sat." Ничего модного.
http совпадает с "http" в любом URL. Всё ещё прямолинейно.
Добавляй подстановочные знаки постепенно
. совпадает с любым одним символом. c.t совпадает с "cat", "cot", "cut".
* означает "ноль или больше предыдущего". ca*t совпадает с "ct", "cat", "caat", "caaaaaat".
+ означает "один или больше". ca+t совпадает с "cat" и "caat", но не с "ct".
? означает "ноль или один". colou?r совпадает и с "color", и с "colour".
Классы символов — твои друзья
[aeiou] совпадает с любой гласной. [0-9] совпадает с любой цифрой. [A-Za-z] совпадает с любой буквой.
\d — сокращение для [0-9]. \w совпадает с символами слова (буквы, цифры, подчёркивание). \s совпадает с пробелами.
Эти строительные блоки обрабатывают большинство реальных паттернов.
Якоря контролируют позицию
^ означает "начало строки". $ означает "конец строки".
^Hello совпадает с "Hello world", но не с "Say Hello".
world$ совпадает с "Hello world", но не с "world peace".
Группы захватывают части
Круглые скобки группируют вещи. Они также захватывают для последующего использования.
(\d{3})-(\d{4}) совпадает с "555-1234" и захватывает "555" и "1234" отдельно.
Так ты извлекаешь конкретные данные из совпадения паттерна.
Реальные примеры, объяснённые
Email (упрощённый):
[\w.-]+@[\w.-]+\.\w+
Перевод: символы слова/точки/дефисы, затем @, затем ещё такие же, затем точка, затем символы слова.
Телефонный номер:
\d{3}[-.\s]?\d{3}[-.\s]?\d{4}
Перевод: 3 цифры, необязательный разделитель, 3 цифры, необязательный разделитель, 4 цифры. Совпадает с "555-123-4567", "555.123.4567", "5551234567".
Дата (MM/DD/YYYY):
\d{2}/\d{2}/\d{4}
Перевод: 2 цифры, слэш, 2 цифры, слэш, 4 цифры.
Частые ошибки
Забываешь экранировать специальные символы. . означает "любой символ" в regex. Чтобы совпасть с буквальной точкой, используй \..
Слишком жадный. .* совпадает насколько возможно. Для HTML-тегов <.*> на <b>bold</b> совпадёт с целой строкой, а не только <b>. Используй <.*?> для нежадного совпадения.
Усложнение. Если тебе нужно валидировать email по-настоящему, используй библиотеку. "Правильный" email regex — сотни символов длиной.
Когда не использовать Regex
Парсинг HTML или JSON. Используй правильный парсер.
Сложная логика валидации. Код часто понятнее, чем один массивный паттерн.
Когда строковые методы работают. "hello".startsWith("he") понятнее, чем /^he/.
Regex — это инструмент. Как любой инструмент, он хорош для конкретных задач и неудобен для других. Начинай просто, тестируй по мере создания и не пытайся быть умным. Читаемый regex лучше, чем впечатляющий regex.