Terminologia usada nesta resposta:
- Jogo indica o resultado da execução de seu padrão de RegEx contra sua seqüência assim:
someString.match(regexPattern)
.
- Os padrões correspondentes indicam todas as partes correspondentes da sequência de entrada, todas residindo dentro do matriz de correspondências . Todas estas são instâncias do seu padrão dentro da sequência de entrada.
- Grupos correspondentes indicam todos os grupos a serem capturados, definidos no padrão RegEx. (Os padrões entre parênteses, assim:,
/format_(.*?)/g
onde (.*?)
seria um grupo correspondente.) Estes residem dentro dos padrões correspondentes .
Descrição
Para obter acesso aos grupos correspondentes , em cada um dos padrões correspondentes , você precisa de uma função ou algo semelhante para iterar durante a correspondência . Existem várias maneiras de fazer isso, como mostram muitas das outras respostas. A maioria das outras respostas usa um loop while para iterar todos os padrões correspondentes , mas acho que todos conhecemos os perigos em potencial com essa abordagem. É necessário fazer a comparação entre a e new RegExp()
não apenas o próprio padrão, mencionado apenas em um comentário. Isso ocorre porque o .exec()
método se comporta de maneira semelhante a uma função de gerador - ele para sempre que há uma correspondência , mas mantém sua.lastIndex
a continuar a partir daí na próxima .exec()
chamada.
Exemplos de código
Abaixo está um exemplo de uma função searchString
que retorna um Array
de todos os padrões correspondentes , onde cada match
um é um Array
com todos os grupos correspondentes correspondentes . Em vez de usar um loop while, forneci exemplos usando ambos osArray.prototype.map()
função e uma maneira mais for
eficiente - usando um loop simples .
Versões concisas (menos código, mais açúcar sintático)
Eles têm menos desempenho, porque basicamente implementam um forEach
loop em vez do mais rápido for
.
// 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
Versões de desempenho (mais código, menos açúcar sintático)
// 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
Ainda tenho que comparar essas alternativas com as mencionadas anteriormente nas outras respostas, mas duvido que essa abordagem tenha menos desempenho e menos falhas do que as outras.