Регулярные выражения в JavaScript: синтаксис, методы и лучшие практики

О чём эта статья
Эта статья объясняет базовый синтаксис регулярных выражений в JavaScript, примеры применения (test, exec, replace), основные метасимволы, рекомендации по производительности и безопасность. Включены шпаргалка с шаблонами, чек-листы для ролей и критерии приёмки.
Основной синтаксис регулярных выражений
В JavaScript регулярное выражение можно создать двумя способами:
- Литерал регулярного выражения: паттерн между косыми чертами, опционально с флагом.
- Конструктор RegExp: new RegExp(‘pattern’, ‘flags’).
Примеры:
// Литерал без флага
const re1 = /pattern/;
// Литерал с флагом
const re2 = /pattern/g;
// Конструктор RegExp (полезен при динамических шаблонах)
const re3 = new RegExp('pattern', 'g');Флаги (наиболее часто используемые):
- g — глобальный поиск (все вхождения).
- i — нечувствительность к регистру.
- m — многострочный режим (влияет на ^ и $).
- s — точка (.) матчится с символом новой строки.
- u — Unicode-режим (правильная работа с суррогатными парами и Unicode-символами).
- y — sticky: матч начинается с текущей позиции lastIndex.
Флаги можно комбинировать: /pattern/gi или new RegExp(‘pattern’, ‘gi’).
Метасимволы и их смысл
Ниже — часто используемые метасимволы. Определения краткие; для практики — см. шпаргалку в конце.
- . — любой символ, кроме перевода строки (в режиме s — включая перенос строки).
- — ноль или более повторений предыдущего токена.
- — одно или более повторений предыдущего токена.
- ? — ноль или одно вхождение (также делает квантификатор ленивым при постфиксе ?).
- ^ — начало строки/строки.
- $ — конец строки/строки.
- [] — символьный класс, например [abc] или [0-9A-Za-z].
- | — альтернация (логическое ИЛИ).
- () — группа и захват (capture group).
- \d, \w, \s — цифровой, буквенно-цифровой и пробельный классы соответственно (экранируйте слэш в JSON-представлении кода).
- {n}, {n,}, {n,m} — точное/минимальное/диапазонное число повторений.
Важно: многие символы имеют специальное значение и при желании поиска буквальных символов должны экранироваться обратным слэшем: ., *, +, \?, \^, \$, [, \ и т.д.
Проверка строки: test, exec и replace
JavaScript предоставляет несколько методов для работы с регулярными выражениями.
Метод test
.test(string) возвращает true или false — удобно для простых проверок.
let regex = /.com$/;
let str = 'example.com';
console.log(regex.test(str)); // trueЭто выражение соответствует строкам, оканчивающимся на “.com”.
Метод exec
.exec(string) возвращает массив совпадений (с захваченными группами) или null, если совпадения нет. Полезен для извлечения частей строки.
let phone = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
let str = '123-456-7890';
let result = phone.exec(str);
if (result !== null) {
console.log(result[0] + ' — корректный телефон');
} else {
console.log('Некорректный телефон');
}В этом примере регулярное выражение распознаёт форматы (xxx) xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx и xxx xxx xxxx.
Замечание: при использовании флага g метод exec запоминает позицию lastIndex, поэтому вызывая exec в цикле, вы получаете последовательно все совпадения.
Метод replace
.replace(pattern, replacement) заменяет найденные совпадения шаблона на строку замены. Если передан флаг g — заменяет все вхождения.
let s = 'The quick brown fox jumps over the lazy dog.';
let re = /the/gi;
let newS = s.replace(re, 'a');
console.log(newS); // 'a quick brown fox jumps over a lazy dog.'В строке выше выражение /the/gi найдёт ‘The’ и заменит на ‘a’, невзирая на регистр.
Когда использовать регулярные выражения и когда нет
Регулярные выражения отлично подходят для:
- Валидации строгих шаблонов (почты, телефонов, форматов идентификаторов).
- Извлечения структурированных фрагментов текста (парсинг простых логов).
- Быстрой замены по шаблону.
Не используйте регулярные выражения, когда:
- Задача требует парсинга вложенной структуры (HTML, XML, JSON) — лучше использовать парсер.
- Шаблон слишком сложен и нечитаем — поддержка станет проблемой.
- Нужно обрабатывать двоичные данные или очень большие тексты с потенциально катастрофическими квантификаторами — риски ReDoS.
Примеры альтернатив:
- Для простых проверок: includes(), startsWith(), endsWith().
- Для разбора CSV/JSON/HTML: специализированные парсеры.
Производительность и безопасность
Рекомендации:
- Делайте шаблоны как можно конкретнее: вместо “.*” используйте ограниченные классы, если возможно.
- Избегайте неоптимальных вложенных квантификаторов, например “.*(a+)+” — это риск ReDoS.
- При обработке входящих данных с неопределённой длиной ограничивайте время/количество итераций на стороне сервера.
- При тестировании паттернов используйте реальные данные и инструменты профилирования.
Безопасность: некоторые регулярные выражения позволяют запустить экспоненциальное число шагов сопоставления для специально сформированных входных данных. Это называется Regular Expression Denial of Service (ReDoS). Всегда тестируйте критичные шаблоны на максимально длинных и злонамеренных строках.
Шпаргалка: часто используемые шаблоны
- Цифры: /\d+/ — одно или более цифровых символов.
- Только буквы латинского алфавита: /^[A-Za-z]+$/.
- E-mail (упрощённая проверка): /^[^\s@]+@[^\s@]+.[^\s@]+$/.
- URL (упрощённая): /https?:\/\/[^\s/$.?#].[^\s]*/i.
- Дата YYYY-MM-DD: /^\d{4}-\d{2}-\d{2}$/.
- UUID v4 (упрощённо): /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[4][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/.
Замечание: сложные стандарты (полный синтаксический анализ email по RFC) требуют специальных парсеров; простая проверка часто достаточна.
Примеры использования и сценарии
- Валидация формы: используйте .test() для быстрого булева ответа.
- Извлечение данных из лога: применяйте exec() или matchAll() для захвата групп.
- Массовая замена: применяйте .replace() с флагом g или функцией-заменителем для сложных преобразований.
Пример: извлечь все хэштеги из текста:
const text = 'Это #тест и #пример регулярных выражений';
const tags = [...text.matchAll(/#(\w+)/g)].map(m => m[1]);
console.log(tags); // ['тест', 'пример']Алгоритм выбора: regex или нет
flowchart TD
A[Есть задача с текстом?] --> B{Нужна ли вложенная
структура 'XML/HTML/JSON'?}
B -- Да --> C[Использовать парсер]
B -- Нет --> D{Задача — валидация,
поиск или замена?}
D -- Поиск/Извлечение --> E[Использовать regex]
D -- Простая проверка --> F[includes/startsWith]
D -- Парсинг сложный --> C
E --> G[Тест и оптимизация]Чек-лист по ролям
Разработчик:
- Проверить читаемость и покрытие тестами регулярных выражений.
- Ограничить размер входных данных при проверке критичных шаблонов.
- Документировать назначение и пример использования.
Тестировщик:
- Подготовить позитивные и негативные тесты (корректные, максимально длинные, злонамеренные строки).
- Проверить поведение при Unicode-символах.
DevOps/Эксплуататор:
- Настроить метрики времени выполнения и лимиты для пользовательских вводов.
- Мониторить ошибки и увеличившуюся латентность при обработке текстов.
Критерии приёмки
- Все пользовательские сценарии валидации проходят автоматические тесты.
- Набор тестов включает крайние случаи и злонамеренные входы.
- Регулярные выражения задокументированы: назначение, примеры и ограничения.
- Производительность на реальных данных соответствует SLA/ожиданиям.
Тест-кейсы и примеры приёмки
- Валидация email: корректные и некорректные адреса.
- Функция извлечения телефонов: форматы с дефисами, точками, пробелами и в скобках.
- Замена слова: проверка регистра и количества замен.
- Нагрузочный тест: длинные строки с шаблонами, провоцирующими бэк-трекинг.
Когда регулярные выражения ломаются: примеры
- Попытка распарсить HTML регулярками приведёт к неустойчивости при вложенности и атрибутах.
- Шаблоны с множественными вложенными квантификаторами могут сильно замедлять работу (ReDoS).
- Некорректная обработка Unicode: без флага u может неправильно работать с эмодзи и комбинирующими символами.
Альтернативные подходы
- Для простых задач используйте методы строк: indexOf, includes, split, slice.
- Для сложной грамматики применяйте парсеры (peg.js, sax, DOMParser).
- Для экстракции сущностей используйте NLP-инструменты при необходимости семантического анализа.
Шпаргалка по безопасности и жёсткие рекомендации
- Всегда тестируйте на злонамеренных строках, особенно если паттерн принимается из внешнего ввода.
- Добавьте тайм-ауты или лимит итераций при серверной обработке.
- При возможности избегайте конструкций вида (a+)+ или .?. с неопределёнными границами.
Мини-методология для внедрения regex в проект
- Поставьте задачу и определите ограничения (максимальная длина входа, набор допустимых символов).
- Напишите читаемый шаблон с комментариями (в JS можно строить строку с пояснениями вне RegExp).
- Покройте юнит-тестами позитивные/негативные случаи.
- Проведите нагрузочное тестирование и тесты на ReDoS.
- Документируйте шаблон в репозитории.
Короткий глоссарий (1 строка на термин)
- Регулярное выражение: строка, описывающая шаблон для поиска в тексте.
- Квантификатор: символы *, +, ? или {n,m}, определяющие количество повторений.
- Capturing group: группа в скобках, позволяющая извлечь часть совпадения.
- ReDoS: атака на отказ в обслуживании через экспоненциальный бэк-трекинг в regex.
Заключение
Регулярные выражения — мощный инструмент для работы со строками в JavaScript. Они позволяют быстро валидировать, искать и преобразовывать текст, но требуют аккуратности: поддерживаемость, безопасность и производительность зависят от простоты и конкретности шаблонов. Используйте регулярные выражения там, где они действительно дают преимущество, комбинируйте с простыми строковыми методами и всегда тестируйте на реальных и злонамеренных данных.
Важно: документация, тесты и код-ревью для сложных шаблонов спасают время дальше при поддержке.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента