Термінологія, що використовується у цій відповіді:
- Match показує результат виконання вашого шаблону RegEx проти вашої рядка наступним чином:
someString.match(regexPattern)
.
- Зібрані візерунки вказують на всі відповідні частини вхідного рядка, які всі знаходяться всередині відповідного масиву. Це всі випадки вашого шаблону всередині вхідного рядка.
- Зібрані групи позначають усі групи для лову, визначені в шаблоні RegEx. (Шаблони всередині дужок, як-от так:,
/format_(.*?)/g
де (.*?)
була б відповідна група.) Вони знаходяться у відповідних шаблонах .
Опис
Щоб отримати доступ до відповідних груп , у кожному зі зібраних шаблонів вам потрібна функція або щось подібне до повторення матчу . Існує ряд способів зробити це, як показує багато інших відповідей. Більшість інших відповідей використовують цикл часу, щоб перебрати всі відповідні шаблони , але я думаю, що всі ми знаємо потенційні небезпеки при такому підході. Потрібно відповідати new RegExp()
замість просто того самого шаблону, про який згадували лише в коментарі. Це відбувається тому, що .exec()
метод поводиться аналогічно функції генератора - він зупиняється щоразу, коли є збіг , але зберігає його .lastIndex
для продовження звідти під час наступного .exec()
дзвінка.
Приклади коду
Нижче наводиться приклад функції, searchString
яка повертає Array
всі відповідні шаблони , де кожен match
є an Array
зі всіма відповідними групами . Замість використання циклу while я наводив приклади, що використовують як Array.prototype.map()
функцію, так і більш ефективний спосіб - використовуючи звичайний for
-loop.
Короткі версії (менше коду, більше синтаксичного цукру)
Вони менш ефективні, оскільки в основному вони реалізують forEach
-loop замість швидшого for
-loop.
// Concise ES6/ES2015 syntax
const searchString =
(string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
// Or if you will, with ES5 syntax
function searchString(string, pattern) {
return string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Виконавчі версії (більше коду, менше синтаксичного цукру)
// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};
// Same thing, but with ES5 syntax
function searchString(string, pattern) {
var result = [];
var matches = string.match(new RegExp(pattern.source, pattern.flags));
for (var i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Мені ще доводиться порівнювати ці альтернативи з тими, які раніше згадувалися в інших відповідях, але я сумніваюся, що такий підхід є менш ефективним і менш безпечним, ніж інші.