Expresión regular para obtener una cadena entre dos cadenas en JavaScript
La solución más completa que funcionará en la gran mayoría de los casos es usar un grupo de captura con un patrón de coincidencia de puntos diferidos . Sin embargo, un punto .
en JavaScript expresión regular no coincide con caracteres de salto de línea, por lo que, lo que va a funcionar en 100% de los casos es un [^]
o [\s\S]
/ [\d\D]
/ [\w\W]
construcciones.
ECMAScript 2018 y una solución compatible más nueva
En entornos JavaScript que admiten ECMAScript 2018 , el s
modificador permite .
hacer coincidir cualquier carácter, incluidos los caracteres de salto de línea, y el motor regex admite retrospectivas de longitud variable. Entonces, puedes usar una expresión regular como
var result = s.match(/(?<=cow\s+).*?(?=\s+milk)/gs); // Returns multiple matches if any
// Or
var result = s.match(/(?<=cow\s*).*?(?=\s*milk)/gs); // Same but whitespaces are optional
En ambos casos, la posición actual se verifica cow
con cualquier 1/0 o más espacios en blanco después cow
, luego se iguala y consume cualquier carácter de 0+ lo menos posible (= agregado al valor de coincidencia), y luego milk
se verifica (con cualquier 1/0 o más espacios en blanco antes de esta subcadena).
Escenario 1: entrada de línea única
Este y todos los demás escenarios a continuación son compatibles con todos los entornos JavaScript. Ver ejemplos de uso al final de la respuesta.
cow (.*?) milk
cow
se encuentra en primer lugar, a continuación, un espacio, entonces cualquier 0+ caracteres distintos de caracteres de salto de línea, tan pocos como sea posible como *?
es un cuantificador perezoso, son capturados en el Grupo 1 y luego un espacio con milk
debe seguir (y aquellos se emparejan y consume , también )
Escenario 2: entrada multilínea
cow ([\s\S]*?) milk
Aquí, cow
y se hace coincidir un espacio primero, luego se combinan los caracteres 0+ lo menos posible y se capturan en el Grupo 1, y luego milk
se hace coincidir un espacio con .
Escenario 3: coincidencias superpuestas
Si tiene una cadena como >>>15 text>>>67 text2>>>
y necesita obtener 2 coincidencias entre >>>
+ number
+ whitespace
y >>>
, no puede usar, />>>\d+\s(.*?)>>>/g
ya que esto solo encontrará 1 coincidencia debido a que el >>>
anterior 67
ya se consume al encontrar la primera coincidencia. Puede utilizar una búsqueda anticipada positiva para verificar la presencia del texto sin realmente "engullirlo" (es decir, agregarlo a la coincidencia):
/>>>\d+\s(.*?)(?=>>>)/g
Vea el rendimiento de la demostración de expresiones regulares en líneatext1
y los text2
contenidos del Grupo 1 encontrados.
Consulte también Cómo obtener todas las coincidencias superpuestas posibles para una cadena .
Consideraciones de rendimiento
El patrón de coincidencia de puntos diferidos ( .*?
) dentro de los patrones de expresiones regulares puede ralentizar la ejecución del script si se proporciona una entrada muy larga. En muchos casos, la técnica de desenrollar el bucle ayuda en mayor medida. Intentando tomar todo entre cow
y milk
desde "Their\ncow\ngives\nmore\nmilk"
, vemos que solo necesitamos unir todas las líneas que no comienzan milk
, por lo tanto, en lugar de cow\n([\s\S]*?)\nmilk
poder usar:
/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm
Vea la demostración de expresiones regulares (si puede haberla \r\n
, úsela /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm
). Con esta pequeña cadena de prueba, la ganancia de rendimiento es insignificante, pero con un texto muy grande, sentirá la diferencia (especialmente si las líneas son largas y los saltos de línea no son muy numerosos).
Ejemplo de uso de expresiones regulares en JavaScript:
//Single/First match expected: use no global modifier and access match[1]
console.log("My cow always gives milk".match(/cow (.*?) milk/)[1]);
// Multiple matches: get multiple matches with a global modifier and
// trim the results if length of leading/trailing delimiters is known
var s = "My cow always gives milk, thier cow also gives milk";
console.log(s.match(/cow (.*?) milk/g).map(function(x) {return x.substr(4,x.length-9);}));
//or use RegExp#exec inside a loop to collect all the Group 1 contents
var result = [], m, rx = /cow (.*?) milk/g;
while ((m=rx.exec(s)) !== null) {
result.push(m[1]);
}
console.log(result);
Usando el String#matchAll
método moderno
const s = "My cow always gives milk, thier cow also gives milk";
const matches = s.matchAll(/cow (.*?) milk/g);
console.log(Array.from(matches, x => x[1]));