Регулярные выражения в JavaScript
Регулярные выражения в JavaScript: создание шаблонов, флаги, ключевые методы string и RegExp, поиск и валидация текста.
Введение в регулярные выражения (Regex) в JavaScript
Регулярные выражения, широко известные как regex, — это последовательности символов, образующие шаблоны поиска. Они являются незаменимыми инструментами программирования для обработки текста: поиска, редактирования и манипулирования строковыми данными. Regex применяется в самых разных областях: валидация данных, парсинг, подсветка синтаксиса и многое другое.
Например, можно быстро проверить, похожа ли строка на адрес электронной почты:
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailRegex.test("[email protected]")); // true
console.log(emailRegex.test("not-an-email")); // falseПримечание: это упрощённый шаблон. Для валидации в продакшене рассмотрите более строгие правила или специализированные библиотеки.
Где используется regex:
- Веб-разработка: валидация полей форм, разбор URL и поиск по содержимому.
- Анализ данных: извлечение конкретных шаблонов из больших наборов данных.
- Редактирование текста: поиск и замена текста в документах или кодовых базах.
- Языки программирования: большинство современных языков, включая JavaScript, поддерживают regex.
Создание регулярного выражения
JavaScript предоставляет два способа создания regex, и разница между ними важна на практике.
// 1. Literal syntax — compiled once when the script loads.
const re1 = /\d+/g;
// 2. Constructor — useful when the pattern is built from a variable.
const word = "cat";
const re2 = new RegExp(word + "s?", "i"); // matches "cat" or "cats", case-insensitive
console.log(re1 instanceof RegExp); // true
console.log(re2.source, re2.flags); // cats? iИспользуйте литеральный синтаксис для фиксированных шаблонов — он короче, и движок компилирует его заранее. К конструктору RegExp обращайтесь, когда шаблон формируется динамически (например, из пользовательского ввода). Помните, что в строке обратный слеш нужно удваивать: "\\d" в конструкторе эквивалентно \d в литерале.
Как regex связан со строками: ключевые методы
Шаблон полезен только вместе с методом, который его выполняет. Вот те, которые вы будете использовать каждый день.
const text = "The year 2023 follows 2022.";
// test() → boolean: "does it match anywhere?"
console.log(/\d{4}/.test(text)); // true
// String.match() with /g → array of all matches
console.log(text.match(/\d{4}/g)); // [ '2023', '2022' ]
// String.replace() → returns a new string
console.log(text.replace(/\d{4}/g, "YEAR")); // The year YEAR follows YEAR.
// RegExp.exec() → one match at a time, with capture groups
console.log(/(\d{4})/.exec(text)[1]); // 2023
// String.matchAll() → iterator of full match objects (needs /g)
for (const m of text.matchAll(/(\d{4})/g)) {
console.log(m[0], "at index", m.index);
}
// 2023 at index 9
// 2022 at index 22Выбирайте метод в зависимости от задачи: test() — для проверки «да/нет», match()/matchAll() — для извлечения данных, replace() — для преобразования текста. Флаг g (глобальный) превращает «первое совпадение» во «все совпадения», поэтому он необходим для match, matchAll и операций замены всех вхождений.
Чтение шаблона: основные строительные блоки
Большинство шаблонов составляется из небольшого набора элементов. Вот рабочий пример, в котором одновременно используется несколько из них:
const log = "2023-06-19 ERROR user=42 path=/login";
// \d digit \w word char \s whitespace
// . any char + 1 or more [] a set of chars
const match = log.match(/(\d{4}-\d{2}-\d{2})\s+(\w+)\s+user=(\d+)/);
console.log(match[1]); // 2023-06-19 (the date group)
console.log(match[2]); // ERROR (the level group)
console.log(match[3]); // 42 (the user id group)Каждый (...) — это захватывающая группа, текст которой попадает в массив результата. \d, \w и \s — это классы символов; квантификаторы + и {4} указывают, сколько раз должен повторяться предшествующий токен. Комбинируя эти элементы, можно извлекать структурированные данные из обычного текста.
Краткий справочник: флаги и квантификаторы
| Категория | Символ/Флаг | Описание |
|---|---|---|
| Флаги | i | Поиск без учёта регистра |
g | Глобальный поиск (найти все совпадения) | |
m | Многострочный режим (^ и $ совпадают с границами строк) | |
s | Режим dotAll (. совпадает с переводами строк). Требует поддержки ES2018+. | |
u | Режим Unicode | |
y | Режим sticky (совпадение только начиная с lastIndex) | |
| Квантификаторы | * | 0 или более раз |
+ | 1 или более раз | |
? | 0 или 1 раз | |
{n} | Ровно n раз | |
{n,} | n или более раз | |
{n,m} | От n до m раз |
Распространённые подводные камни
Несколько сюрпризов, которые подстерегают почти всех при изучении regex в JavaScript:
-
Regex с флагом
/gзапоминает, где остановился. При повторном использовании одного и того же объектаRegExpсtest()илиexec()значениеlastIndexпродвигается между вызовами, поэтому второйtest()может вернутьfalseдля строки, в которой явно есть совпадение. Используйте новый литерал при каждом вызове или сбрасывайтеre.lastIndex = 0.const re = /a/g; const s = "a"; console.log(re.test(s)); // true console.log(re.test(s)); // false — lastIndex moved past the end -
Динамические шаблоны требуют экранирования пользовательского ввода. Если вы строите regex из текста, введённого пользователем, символы вроде
.или(будут интерпретироваться как специальные. Предварительно экранируйте их:const escape = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const userInput = "a.b"; const re = new RegExp(escape(userInput)); console.log(re.test("axb")); // false — the dot is now literal console.log(re.test("a.b")); // true -
По умолчанию квантификаторы жадные.
.+захватывает как можно больше; добавьте?, чтобы сделать его ленивым (.+?). Подробнее: Жадные и ленивые квантификаторы.
Маршрут обучения
Эта страница является отправной точкой раздела курса о регулярных выражениях. Пройдите следующие главы по порядку для полного практического понимания темы:
- Шаблоны и флаги — построение шаблонов и влияние флагов (
i,g,m,s,u,y) на поиск. - Классы символов —
\d,\w,\sи их отрицания. - Unicode: флаг
uи класс\p{...}— работа с многоязычным текстом и эмодзи. - Якоря: начало строки
^и конец$— совпадение на границах. - Многострочный режим якорей, флаг
m— привязка^и$к каждой строке. - Граница слова
\b— поиск целых слов. - Экранирование специальных символов — использование
.,(,?как обычных символов. - Наборы и диапазоны
[...]— пользовательские наборы символов. - Квантификаторы
+,*,?,{n}— указание количества повторений. - Жадные и ленивые квантификаторы — управление объёмом захвата.
- Захватывающие группы — извлечение и именование частей совпадения.
- Обратные ссылки
\nи\k<name>— повторное использование захваченного текста. - Альтернация (ИЛИ)
|— совпадение с одним из нескольких вариантов. - Опережающая и ретроспективная проверка — утверждения нулевой ширины.
- Катастрофический откат — диагностика и предотвращение патологической производительности.
- Флаг sticky
y, поиск с заданной позиции — привязанный поиск на основе позиции.
Описание методов, выполняющих эти шаблоны, см. в главах Объект RegExp и его методы и Строки в JavaScript.
Пройдя все эти уроки, вы сможете создавать эффективные шаблоны regex для поиска, валидации и преобразования текста в JavaScript.