Terminología utilizada en esta respuesta:
- Partido indica el resultado de ejecutar el patrón de expresión en contra de su cadena de este modo:
someString.match(regexPattern)
.
- Los patrones coincidentes indican todas las partes coincidentes de la cadena de entrada, que residen todas dentro de la matriz de coincidencias . Estas son todas las instancias de su patrón dentro de la cadena de entrada.
- Los grupos coincidentes indican todos los grupos a capturar, definidos en el patrón RegEx. (Los patrones dentro de paréntesis, así:
/format_(.*?)/g
dónde (.*?)
sería un grupo coincidente). Estos residen dentro de patrones coincidentes .
Descripción
Para obtener acceso a los grupos coincidentes , en cada uno de los patrones coincidentes , necesita una función o algo similar para iterar sobre la coincidencia . Hay varias formas de hacerlo, como muestran muchas de las otras respuestas. La mayoría de las otras respuestas usan un ciclo while para iterar sobre todos los patrones coincidentes , pero creo que todos conocemos los peligros potenciales con ese enfoque. Es necesario hacer coincidir un new RegExp()
patrón en lugar de solo el patrón en sí mismo, que solo se mencionó en un comentario. Esto se debe a que el .exec()
método se comporta de manera similar a una función generadora : se detiene cada vez que hay una coincidencia , pero .lastIndex
continúa desde allí en la próxima .exec()
llamada.
Ejemplos de código
A continuación se muestra un ejemplo de una función searchString
que devuelve uno Array
de todos los patrones coincidentes , donde cada uno match
es un Array
con todos los grupos coincidentes que contienen . En lugar de usar un bucle while, he proporcionado ejemplos usando tanto la Array.prototype.map()
función como una forma más for
eficiente : usando un bucle simple .
Versiones concisas (menos código, más azúcar sintáctico)
Estos son menos forEach
efectivos ya que básicamente implementan un bucle en lugar del for
bucle más rápido.
// 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
Versiones de rendimiento (más código, menos azúcar sintáctico)
// 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
Todavía tengo que comparar estas alternativas con las mencionadas anteriormente en las otras respuestas, pero dudo que este enfoque sea menos eficaz y menos a prueba de fallas que los otros.