Антон Ларичев

Введение
Регулярные выражения в JavaScript — один из самых мощных инструментов для работы со строками. С их помощью можно искать подстроки по шаблону, валидировать пользовательский ввод и выполнять сложные замены. Несмотря на устрашающий синтаксис, регулярки поддаются изучению, если разобраться в базовых концепциях последовательно.
Создание регулярного выражения
В JavaScript регулярное выражение — это объект типа RegExp. Его можно создать двумя способами.
Литеральный синтаксис (предпочтительный для статических шаблонов):
const regex = /javascript/i; // ищем слово без учёта регистра
Через конструктор (когда шаблон динамический):
const keyword = 'javascript';
const regex = new RegExp(keyword, 'i'); // шаблон формируется из переменной
Используйте конструктор, когда шаблон известен только во время выполнения программы, например строится из пользовательского ввода.
Основные метасимволы
Метасимволы — специальные символы с особым значением в регулярных выражениях.
| Символ | Значение |
|---|---|
. | Любой символ кроме переноса строки |
\d | Цифра (0–9) |
\w | Буква, цифра или _ |
\s | Пробельный символ |
^ | Начало строки |
$ | Конец строки |
const emailRegex = /^\w+@\w+\.\w+$/;
console.log(emailRegex.test('user@mail.ru')); // true
console.log(emailRegex.test('не email')); // false
Заглавные версии (\D, \W, \S) означают противоположное: не цифра, не буква, не пробел.
Квантификаторы
Квантификаторы задают количество повторений предшествующего элемента.
// * — ноль или более повторений
// + — одно или более повторений
// ? — ноль или одно повторение
// {n,m} — от n до m повторений
const phoneRegex = /^\+7\d{10}$/;
console.log(phoneRegex.test('+79991234567')); // true
console.log(phoneRegex.test('+7999')); // false — меньше 10 цифр
По умолчанию квантификаторы «жадные» — захватывают максимально длинную подстроку. Добавьте ? после квантификатора, чтобы сделать его «ленивым»:
const html = '<b>жирный</b> и <b>ещё жирный</b>';
const жадный = html.match(/<b>.*<\/b>/);
console.log(жадный[0]); // '<b>жирный</b> и <b>ещё жирный</b>'
const ленивый = html.match(/<b>.*?<\/b>/);
console.log(ленивый[0]); // '<b>жирный</b>' — остановился на первом совпадении
Флаги
Флаги меняют поведение регулярного выражения и указываются после закрывающего слэша.
const text = 'JavaScript — это javascript и JAVASCRIPT';
// g — глобальный поиск (все совпадения)
// i — без учёта регистра
// m — многострочный режим
const matches = text.match(/javascript/gi);
console.log(matches); // ['JavaScript', 'javascript', 'JAVASCRIPT']
Флаг s (dotAll) заставляет . совпадать в том числе с символами переноса строки — полезно при парсинге многострочного текста.
Методы работы с регулярными выражениями
test и exec — методы RegExp
const regex = /\d+/;
// test — возвращает true/false
console.log(regex.test('в тексте 42 символа')); // true
// exec — возвращает массив с деталями совпадения или null
const result = regex.exec('в тексте 42 символа');
console.log(result[0]); // '42' — найденная подстрока
console.log(result.index); // 9 — позиция начала совпадения
match, matchAll, replace — методы String
const str = 'Цена: 100 рублей, скидка: 20 рублей';
// match с флагом g возвращает все совпадения
const prices = str.match(/\d+/g);
console.log(prices); // ['100', '20']
// matchAll возвращает итератор с подробной информацией
for (const match of str.matchAll(/\d+/g)) {
console.log(`Найдено: ${match[0]} на позиции ${match.index}`);
}
// replace с функцией-обработчиком
const doubled = str.replace(/\d+/g, (num) => num * 2);
console.log(doubled); // 'Цена: 200 рублей, скидка: 40 рублей'
Группы захвата
Круглые скобки создают группу захвата — часть шаблона, к которой можно обратиться отдельно.
const dateStr = '2024-03-15';
const dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
const match = dateStr.match(dateRegex);
console.log(match[1]); // '2024' — год
console.log(match[2]); // '03' — месяц
console.log(match[3]); // '15' — день
Именованные группы делают код значительно читаемее:
const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const { year, month, day } = dateStr.match(regex).groups;
console.log(year, month, day); // '2024' '03' '15'
Чтобы сгруппировать элементы без захвата, используйте (?:...) — такая группа не попадает в match и не тратит память.
Частые ошибки
1. Забыть экранировать спецсимволы
Символы ., *, +, ?, (, ), [, ], {, }, `, ^, $, | имеют специальное значение. Чтобы использовать их буквально, поставьте перед ними `:
// неправильно — точка совпадёт с любым символом
const wrong = /3.14/;
console.log(wrong.test('3X14')); // true — неожиданный результат
// правильно — экранируем точку
const correct = /3\.14/;
console.log(correct.test('3X14')); // false
2. Забыть флаг g при замене всех вхождений
const str = 'foo foo foo';
console.log(str.replace(/foo/, 'bar')); // 'bar foo foo' — только первое
console.log(str.replace(/foo/g, 'bar')); // 'bar bar bar' — все вхождения
3. Переиспользование exec с флагом g без сброса lastIndex
При флаге g объект RegExp хранит позицию последнего совпадения в lastIndex. Если переиспользовать один объект, следующий поиск начнётся не с начала строки:
const regex = /\d+/g;
const str = 'a1 b2 c3';
console.log(regex.exec(str)); // ['1'], lastIndex = 2
console.log(regex.exec(str)); // ['2'], lastIndex = 5
console.log(regex.exec(str)); // ['3'], lastIndex = 8
console.log(regex.exec(str)); // null — поиск начат с конца строки!
// решение: используйте matchAll или сбрасывайте lastIndex
regex.lastIndex = 0;
4. Катастрофический возврат (ReDoS)
Вложенные квантификаторы на перекрывающихся группах могут вызвать экспоненциальное время выполнения на специально составленных строках:
// опасный паттерн — не используйте в production без проверки
const dangerous = /^(a+)+$/;
// для строки 'aaaaaaaaab' движок перебирает экспоненциальное число вариантов
Проверяйте паттерны с граничными входными данными и используйте инструменты анализа вроде safe-regex.
Заключение
Регулярные выражения в JavaScript — незаменимый инструмент для валидации форм, парсинга текста и трансформации данных. Начните с базовых метасимволов и методов test, match, replace, затем переходите к группам захвата, флагам и «ленивым» квантификаторам. Проверяйте регулярки на сервисе regex101.com — там видно пошаговое совпадение и объяснение каждой части шаблона. Со временем синтаксис станет интуитивным и перестанет пугать.






Комментарии
0