Как получить доступ к совпавшим группам в регулярном выражении JavaScript?
Основы работы с группами захвата в JavaScript
В регулярных выражениях группы захвата (capturing groups) — это части шаблона, заключённые в круглые скобки (). Они позволяют извлечь подстроки, соответствующие этим частям. В JavaScript есть несколько способов получить к ним доступ.
Метод exec()
Метод RegExp.prototype.exec() возвращает массив с совпадениями. Нулевой элемент — это полное совпадение, а элементы с 1 по N — это группы захвата:
let str = "Сегодня 25.12.2023";
let regex = /(\d{2})\.(\d{2})\.(\d{4})/;
let result = regex.exec(str);
console.log(result[0]); // "25.12.2023" (полное совпадение)
console.log(result[1]); // "25" (день)
console.log(result[2]); // "12" (месяц)
console.log(result[3]); // "2023" (год)
Если совпадений нет, exec() возвращает null, что удобно для проверки:
if (result) {
console.log(`День: ${result[1]}, Месяц: ${result[2]}, Год: ${result[3]}`);
} else {
console.log("Дата не найдена");
}
Метод match()
Метод String.prototype.match() ведёт себя по-разному в зависимости от флага g:
- Без флага
g: возвращает тот же массив, что иexec()— с группами захвата. - С флагом
g: возвращает только полные совпадения без групп. Это частая ловушка для новичков.
// Без g — работает как exec()
let match1 = str.match(/(\d{2})\.(\d{2})\.(\d{4})/);
console.log(match1[1]); // "25"
// С g — только полные совпадения
let match2 = str.match(/(\d{2})\.(\d{2})\.(\d{4})/g);
console.log(match2); // ["25.12.2023"]
console.log(match2[1]); // undefined!
Именованные группы захвата (ES2018)
Начиная с ES2018, вы можете давать группам имена с помощью синтаксиса (?<name>...). Это делает код читаемее:
let regex = /(?<day>\d{2})\.(?<month>\d{2})\.(?<year>\d{4})/;
let result = regex.exec(str);
if (result) {
console.log(result.groups.day); // "25"
console.log(result.groups.month); // "12"
console.log(result.groups.year); // "2023"
}
Именованные группы также работают с match() (без флага g).
Глобальный поиск с exec() в цикле
Если нужно найти все совпадения с группами, используйте exec() в цикле while:
let str = "Даты: 25.12.2023, 01.01.2024, 15.06.2025";
let regex = /(\d{2})\.(\d{2})\.(\d{4})/g;
let match;
while ((match = regex.exec(str)) !== null) {
console.log(`День: ${match[1]}, Месяц: ${match[2]}, Год: ${match[3]}`);
}
Метод matchAll() (ES2020)
Современная альтернатива — String.prototype.matchAll(). Он возвращает итератор, который можно обойти с помощью for...of или развернуть в массив:
let matches = str.matchAll(/(\d{2})\.(\d{2})\.(\d{4})/g);
for (let match of matches) {
console.log(`День: ${match[1]}, Месяц: ${match[2]}, Год: ${match[3]}`);
}
// Или с именованными группами
let namedMatches = str.matchAll(/(?<day>\d{2})\.(?<month>\d{2})\.(?<year>\d{4})/g);
for (let match of namedMatches) {
console.log(match.groups.day);
}
Краткие рекомендации
- Используйте
exec()для одного совпадения с проверкой наnull. - Используйте
match()безgесли вам не нужен глобальный поиск. - Используйте
matchAll()илиexec()в цикле для глобального поиска с группами. - Применяйте именованные группы
(?<name>...)для повышения читаемости.
Деструктуризация для удобства
Если вы не хотите каждый раз писать result[1], можно использовать деструктуризацию массива. Это особенно удобно, когда групп немного:
let str = "25.12.2023";
let [, day, month, year] = str.match(/(\d{2})\.(\d{2})\.(\d{4})/) || [];
console.log(day, month, year); // "25" "12" "2023"
Обратите внимание на запятую в начале — она пропускает нулевой элемент (полное совпадение). Оператор || [] защищает от ошибки, если совпадений нет.
Метод replace() с функцией
Иногда удобно использовать String.prototype.replace() с колбэком. Второй аргумент может быть функцией, которая получает группы как отдельные параметры:
let str = "25.12.2023";
let result = {};
str.replace(/(\d{2})\.(\d{2})\.(\d{4})/, (match, day, month, year) => {
result = { day, month, year };
});
console.log(result); // { day: "25", month: "12", year: "2023" }
Этот подход полезен, когда нужно одновременно извлечь данные и выполнить замену в строке.
Библиотека XRegExp для продвинутых случаев
Если вам нужны дополнительные возможности (например, поддержка Unicode или расширенный синтаксис), обратите внимание на библиотеку XRegExp. Она добавляет именованные группы для старых браузеров и другие полезные функции.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
PHP или Python для бэкенда: что выбрать в 2024 году?