Гид по технологиям

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

7 min read Programming Обновлено 07 Jan 2026
Регулярные выражения в JavaScript — основы и практика
Регулярные выражения в JavaScript — основы и практика

Лупа и фрагмент кода с регулярными выражениями

О чём статья

Я объясню, что такое регулярные выражения, как их писать и тестировать в JavaScript, приведу практические примеры и чек-листы для разработчика и тестировщика. Также разберём ситуации, когда regex не подходит, и альтернативы.

Кому полезно: начинающим разработчикам и инженерам качества, которые работают с валидацией, извлечением и трансформацией строк.


Краткое определение

Регулярное выражение — строка, описывающая шаблон поиска в тексте. Простое правило: чем конкретнее шаблон, тем быстрее и надёжнее он работает.

Основной синтаксис регулярных выражений в JavaScript

Есть два способа создать регулярное выражение:

  • Литерал: шаблон между прямыми слешами. Например:
// Без флага
const regexExpression_1 = /pattern/;

// С флагом
const regexExpression_2 = /pattern/gi;
  • Конструктор RegExp:
const regexExpression = new RegExp("Pattern", "g");

Флаги — необязательные параметры, которые изменяют поведение шаблона. Частые флаги:

  • g — глобальный поиск (все совпадения);
  • i — нечувствительность к регистру;
  • m — многострочный режим (якоря ^ и $ работают для начала/конца строки);
  • s — режим «dotAll»: точка (.) также совпадает с символом новой строки (ES2018+);
  • u — режим Unicode; нужен при работе с суррогатными парами и кодовыми точками;
  • y — «sticky» — поиск с привязкой к текущей позиции (редко используемый).

Применение нескольких флагов:

const regexExpression = new RegExp("Pattern", "gi");

Этот пример найдёт все вхождения “Pattern” независимо от регистра.

Метасимволы и классы символов

Ниже — список часто используемых метасимволов и короткие пояснения с примерами.

  • . — любой одиночный символ, кроме перевода строки (в режиме s точка совпадает и с переводом строки).
    • — предыдущий элемент 0 и более раз (жадный квантификатор).
    • — предыдущий элемент 1 и более раз.
  • ? — предыдущий элемент 0 или 1 раз; также делает квантификатор ленивым при добавлении ? после него.
  • {n} {n,} {n,m} — точное/минимальное/диапазонное количество повторов.
  • ^ — начало строки/строки (в режиме m — начала каждой строки).
  • $ — конец строки/строки.
  • [] — класс символов; например, [aeiou] совпадёт с любой гласной.
  • [^…] — отрицательный класс; [^0-9] — любой символ, не являющийся цифрой.
  • | — альтернатива (логическое ИЛИ). Пример: cat|dog.
  • () — захватывающая группа; позволяет извлекать подстроки и применять квантификаторы к группе.
  • (?:…) — негруппирующая (non-capturing) группа; используется для группировки без сохранения в результат.
  • \d, \D, \w, \W, \s, \S — сокращения: цифры/не-цифры, «слово»/не-слово, пробел/не-пробел.
  • \b, \B — граница слова / не граница слова.
  • (?=…), (?!…) — позитивный/негативный просмотр вперёд (lookahead).
  • (?<=…), (?

Примеры:

// Любая почта простого вида
const email = /[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}/i;

// Номер телефона (US-подобный)
const phone = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;

Важно: квадратные скобки [] и экранирование символов работают по своим правилам: внутри [] многие метасимволы теряют особый смысл, но дефис (-) и ^ имеют специальное поведение.

Группы и захват

Группы позволяют взять часть совпадения и получить её отдельно в результате. Порядок групп определяется скобками слева направо.

let regex = /(\d{4})-(\d{2})-(\d{2})/; // Группа 1: год, 2: месяц, 3: день
let date = "2024-01-07";
let result = regex.exec(date);
// result[1] -> "2024"
// result[2] -> "01"
// result[3] -> "07"

Если группа нужна только для группировки (без захвата), используйте (?:…):

const r = /(?:foo|bar)baz/; // Группа не попадёт в массив захвата

Методы проверки и получения совпадений

В JavaScript есть несколько полезных методов для работы с регулярными выражениями.

test

.test(string) возвращает boolean — есть ли совпадение.

let regex = /.com$/;
let str = "example.com";
console.log(regex.test(str)); // true

exec

.exec(string) возвращает массив с совпадением и захваченными группами или null.

let regex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
let str = "123-456-7890";
let result = regex.exec(str);
if (result !== null) {
  console.log(`${result[0]} is a valid phone number`);
} else {
  console.log("Invalid phone number");
}

Если регулярное выражение с флагом g используется многократно с exec, оно запоминает позицию поиска (lastIndex).

match и matchAll

  • str.match(regex) возвращает массив совпадений или массив с группами (в зависимости от флагов).
  • str.matchAll(regex) возвращает итератор для всех совпадений с доступом к группам (полезно для получения всех групп при глобальном поиске).
const text = "a1 b2 c3";
const re = /(\w)(\d)/g;
for (const m of text.matchAll(re)) {
  console.log(m[1], m[2]);
}

replace

str.replace(regex, replacement) заменяет совпадения на replacement. Replacement может быть строкой или функцией.

let string = "The quick brown fox jumps over the lazy dog.";
let expression = /The/gi;
let newString = string.replace(expression, "a");
console.log(newString); // "a quick brown fox jumps over a lazy dog."

// Replacement как функция
let names = "Mr. Smith and Ms. Doe".replace(/(Mr|Ms)\.\s(\w+)/g, (m, title, name) => `${name} (${title})`);
// "Smith (Mr) and Doe (Ms)"

search и split

  • str.search(regex) возвращает индекс первого совпадения или -1.
  • str.split(regex) разбивает строку по совпадениям регулярного выражения.

Жадные и ленивые квантификаторы

По умолчанию квантификаторы жадные — они захватывают как можно больше символов. Добавление ? делает их ленивыми.

const s = "
one
two
"; // Жадный console.log(s.match(/
.*<\/div>/)[0]); // совпадёт с обеими дивами // Ленивый console.log(s.match(/
.*?<\/div>/g)); // два отдельных совпадения

Когда регулярные выражения не подходят

  • Сложная вложенная грамматика (HTML, XML): лучше использовать парсеры.
  • Контекстно-зависимый синтаксис (языки программирования): парсер AST надёжнее.
  • Чувствительность к Unicode-границам без флага u: могут быть ошибки.

Альтернатива: синтаксический разбор на основе грамматик, парсеры, специализированные библиотеки для обработки HTML/JSON.

Типичные ошибки и крайние случаи

  • Неправильное экранирование слешей при использовании конструктора RegExp: new RegExp(“\d+”) вместо new RegExp(“\d+”).
  • Использование глобального флага g с методами, которые возвращают только первый результат (некоторые комбинации приводят к неожиданному lastIndex).
  • Катастрофическое обратное отслеживание (catastrophic backtracking) при вложенных жадных квантификаторах.

Пример плохого паттерна:

// Плохо: (a+)+ приведёт к экспоненциальному времени при длинных строках без совпадения
const bad = /(a+)+b/;

Митигирование: сделать паттерны более конкретными, использовать ленивые квантификаторы, избегать вложения неопределённых квантификаторов.

Производительность и безопасность

  • Чем уже и конкретнее шаблон, тем меньше вероятность затрат на backtracking.
  • Проверяйте входные данные и по возможности ограничивайте длину строки до проверки regex.
  • Для пользовательских шаблонов выполняйте анализ на предмет уязвимости ReDoS (Regular Expression Denial of Service).

Совет: вместо разрешения пользователям вводить произвольные шаблоны предоставьте ограниченный DSL или готовые шаблоны.

Практическая методология создания надёжного регулярного выражения

  1. Чётко опишите цель: что именно нужно найти или извлечь.
  2. Начните с простого, затем постепенно усложняйте шаблон.
  3. Покройте позитивные и негативные тест-кейсы.
  4. Проанализируйте пограничные случаи (пустые строки, неожиданные символы).
  5. Проверяйте производительность на реальных данных.

Чек-листы по ролям

Разработчик:

  • Описана цель шаблона.
  • Используются флаги корректно (g, i, m, s, u).
  • Экранированы специальные символы.
  • Добавлены unit-тесты для позитивных и негативных кейсов.

QA-инженер:

  • Проверить вхождения на реальных данных.
  • Тесты на очень большие строки и невалидные данные.
  • Проверить поведение при режиме многострочности и флаге s.

Инженер безопасности:

  • Поиск потенциального ReDoS-паттерна.
  • Ограничение длины входа перед запуском regex.
  • Логи и метрики выполнения регулярных выражений.

Критерии приёмки

  • Регулярное выражение покрывает все заявленные позитивные тесты.
  • Результаты отрицательных тестов не содержат ложных срабатываний.
  • Производительность соответствует требованиям (не происходит экспоненциального роста времени).
  • Код снабжён комментариями и примерами использования.

Тестовые примеры и критерии

  1. Валидация email (базовый):
  • “user@example.com” -> совпадает
  • “user@sub.domain.org” -> совпадает
  • “user@@example.com” -> не совпадает
  1. Формат телефона (US):
  • “(123) 456-7890” -> совпадает
  • “123-456-7890” -> совпадает
  • “12-3456-7890” -> не совпадает
  1. Извлечение тегов HTML (только демонстрация):
  • На HTML-парсинг использовать парсер, а не regex — тест: “

    text

    ” -> не полагаться на regex для вложенных структур.

Маленькое справочное поле — ключевые факты

  • Конструктор RegExp требует дополнительного экранирования, потому что строка сначала интерпретируется как литерал JavaScript.
  • Lookbehind (?<=…) официально поддерживается в современных движках JavaScript (ES2018+).
  • Флаг s (dotAll) позволяет точке совпадать с переносом строки (ES2018+).

Короткий глоссарий

  • Захват (capture): сохранение части совпадения в массив результатов.
  • Квантификатор: оператор, задающий количество повторов (например, *, +, {2,5}).
  • Backtracking: механизм поиска альтернатив при несовпадении, может привести к ухудшению производительности.

Примеры полезных шаблонов — шпаргалка

// Простая проверка URL (очень базовая)
const url = /https?:\/\/[\w.-]+(?:\.[\w\.-]+)+[\w\-._~:\/?#\[\]@!$&'()*+,;=.]+/i;

// Валидатор IPv4
const ipv4 = /^(25[0-5]|2[0-4]\d|[01]?\d?\d)(\.(25[0-5]|2[0-4]\d|[01]?\d?\d)){3}$/;

// Получить все слова, игнорируя пунктуацию
const words = /\b[\p{L}0-9_-]+\b/gu; // требует флага u для Unicode (ES2018+)

Альтернативные подходы

  • Для структурированных форматов (JSON, XML, HTML) используйте специализированные парсеры.
  • Для простых валидаций достаточно комбинации методов String (startsWith, includes, split) и небольших проверок.

Быстрые рекомендации по локализации и работе с Unicode

  • Всегда используйте флаг u при работе с Unicode-данными и символами за пределами Basic Multilingual Plane.
  • Для поиска слов используйте \p{L} (требует флага u) — это лучший способ охватить буквы разных алфавитов.

Пример реального рабочего сценария: валидация поля ввода на форме

  1. Обрежьте пробелы: value = value.trim();
  2. Проверьте длину: если длиннее N — отклонить.
  3. Примените чистый и определённый regex (не общую «ловушку»).
  4. При неудаче — верните понятное сообщение пользователю.

Часто задаваемые вопросы

Что лучше: RegExp-конструктор или литерал?

Литерал проще и быстрее, если шаблон известен на этапе написания кода. Конструктор полезен, когда шаблон формируется динамически.

Как отладить сложный шаблон?

Используйте онлайн-отладчики (Regex101, Regexper) и добавляйте unit-тесты с разнообразными кейсами. Для локальных данных логируйте время работы.

Чем опасны пользовательские regex?

Пользовательский сложный паттерн может создать ReDoS-уязвимость. Ограничьте длину входа и предоставляйте безопасные шаблоны.


Резюме

  • Регулярные выражения — мощный инструмент для поиска и трансформации текста, но требуют аккуратности.
  • Предпочитайте конкретные шаблоны, проверяйте граничные случаи и избегайте вложенных жадных квантификаторов.
  • Для структурированных данных выбирайте парсеры.

Важно: всегда сопровождайте сложные регулярные выражения комментариями и тестами.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство