Создание
const re1 = / pattern / flags;
const re2 = new RegExp ( 'pattern' , 'flags' ); // когда паттерн динамический
Флаги
Флаг Значение gglobal — все совпадения, не только первое iignore case mmultiline — ^/$ работают по строкам, а не по всей строке sdotAll — . матчит и \n тоже uunicode-режим (важно для эмодзи, суррогатных пар) ysticky — матч строго с позиции lastIndex
Классы символов
Паттерн Значение .любой символ кроме \n (если нет флага s) \d / \Dцифра / не цифра \w / \W[A-Za-z0-9_] / наоборот\s / \Sпробельный / непробельный [abc]один из перечисленных [^abc]любой, кроме перечисленных [a-z], [0-9], [A-Za-z]диапазон
Квантификаторы
Паттерн Значение *0 или больше +1 или больше ?0 или 1 {n}ровно n {n,}n или больше {n,m}от n до m *?, +?, ??, {n,m}?lazy-версии (минимально возможное совпадение)
Greedy vs Lazy:
"<a><b>" . match ( / < . + > / ) // ['<a><b>'] — greedy, всё целиком
"<a><b>" . match ( / < . +? > / ) // ['<a>'] — lazy, минимально
Якоря и границы
Паттерн Значение ^начало строки (или начало после \n с флагом m) $конец строки \bграница слова \BНЕ граница слова
Группы
Паттерн Значение (...)захватывающая группа (?:...)незахватывающая (не попадает в результат) (?<name>...)именованная группа \1, \2обратная ссылка на группу 1, 2 (внутри паттерна) (?=...)lookahead — “за чем следует” (?!...)negative lookahead (?<=...)lookbehind — “перед чем стоит” (?<!...)negative lookbehind
// lookahead пример: число с разделителями тысяч
"1234567" . replace ( / \B (?=( \d {3} ) + (?! \d )) / g , ',' ) // "1,234,567"
Альтернация
/ cat | dog / // "cat" или "dog"
/ colou ? r / // "color" или "colour"
Экранирование спецсимволов
Нужно экранировать: . * + ? ^ $ { } ( ) | [ ] \
const escaped = str. replace ( / [.*+?^${}()|[ \]\\ ] / g , ' \\ $&' );
Основные методы строк/RegExp
Метод Возвращает Когда использовать str.match(re)массив совпадений или null без g — первое + группы; с g — все совпадения без групп str.matchAll(re)итератор (нужен флаг g) все совпадения + группы для каждого str.replace(re, str|fn)новая строка замена (с g — все вхождения) str.replaceAll(re, ...)новая строка требует флаг g у regex str.split(re)массив строк разбиение по паттерну str.search(re)индекс или -1 позиция первого совпадения re.test(str)booleanпросто проверка наличия re.exec(str)массив или null пошаговый перебор (с g двигает lastIndex)
replace с callback и группами
"backgroundColor" . replace ( / [A-Z] / g , m => '-' + m. toLowerCase ())
// "background-color"
"2024-06-20" . replace ( / ( \d + )-( \d + )-( \d + ) / , '$3.$2.$1' )
// "20.06.2024"
// именованные группы в replace
"2024-06-20" . replace ( / (?< y > \d + )-(?< m > \d + )-(?< d > \d + ) / , '$<d>.$<m>.$<y>' )
Частые шаблоны-заготовки
const EMAIL = / ^ [\w.+-] + @ [\w-] + \. [a-z] {2,}$ / i ;
const URL_SIMPLE = / ^ https ? : \/\/ [\w.-] + \. [a-z] {2,} ( \/ \S * ) ?$ / i ;
const INTEGER = / ^ [+-] ? \d +$ / ;
const FLOAT = / ^ [+-] ? \d + ( \. \d + ) ?$ / ;
const HEX_COLOR = / ^ #( [0-9a-f] {3}| [0-9a-f] {6} ) $ / i ;
const WHITESPACE_TRIM = / ^ \s +| \s +$ / g ;
const MULTI_SPACE = / \s + / g ;
const WORD_BOUNDARY_SPLIT = / \b / ;
Частые ловушки
match() без g возвращает группы, с g — нет. Если нужны и все совпадения, и группы — используй matchAll().
exec() в цикле с флагом g использует lastIndex — забыл сбросить или не использовал g → бесконечный цикл или вечный один и тот же результат.
. не матчит перенос строки без флага s.
^/$ без флага m относятся ко всей строке, а не к каждой линии.
Жадные квантификаторы (*, +) могут “захватить” больше, чем ожидаешь — проверяй на lazy (*?, +?).
Regex не умеет считать вложенность (скобки, теги) — для этого нужен парсер/стек (см. LeetCode 394, 10).
regexp