Терминология, использованная в этом ответе:
- Match показывает результат выполнения вашего шаблона RegEx против вашей строки следующим образом:
someString.match(regexPattern)
.
- Совпадающие шаблоны указывают на все совпадающие части входной строки, которые все находятся в массиве совпадений . Это все экземпляры вашего шаблона внутри входной строки.
- Совпадающие группы указывают на все группы, которые нужно поймать, определенные в шаблоне RegEx. (Шаблоны в круглых скобках, например, так
/format_(.*?)/g
, где (.*?)
будет сопоставленная группа.) Они находятся в согласованных шаблонах .
Описание
Чтобы получить доступ к сопоставленным группам , в каждом из сопоставленных шаблонов вам нужна функция или нечто подобное для итерации по совпадению . Есть много способов сделать это, как показывают многие другие ответы. Большинство других ответов используют цикл while для итерации по всем сопоставленным шаблонам , но я думаю, что мы все знаем о потенциальных опасностях такого подхода. Необходимо сопоставлять new RegExp()
вместо самого шаблона, который упоминается только в комментарии. Это связано с тем, что .exec()
метод ведет себя аналогично функции генератора - он останавливается каждый раз, когда происходит совпадение , но сохраняет его .lastIndex
для продолжения оттуда при следующем .exec()
вызове.
Примеры кода
Ниже приведен пример функции, searchString
которая возвращает один Array
из всех сопоставленных шаблонов , где каждый match
представляет собой 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 (больше кода, меньше синтаксического сахара)
// 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
Мне еще предстоит сравнить эти альтернативы с ранее упомянутыми в других ответах, но я сомневаюсь, что этот подход менее эффективен и менее надежен, чем другие.