Espressione regolare per ottenere una stringa tra due stringhe in Javascript

Ho trovato post molto simili ma non riesco a ottenere la mia espressione regolare proprio qui.

Sto cercando di scrivere un’espressione regolare che restituisca una stringa che si trova tra due altre stringhe. Ad esempio: voglio ottenere la stringa che risiede tra le stringhe “mucca” e “latte”

La mia mucca dà sempre latte

sarebbe tornato

“dà sempre”

Ecco l’espressione che ho messo insieme finora:

(?=cow).*(?=milk) 

Tuttavia questo restituisce la stringa “mucca dà sempre”

Un lookahead (che (?= Parte) non consuma alcun input: è un’asserzione di larghezza zero (come i controlli di confine e le schermate).

Vuoi una partita regolare qui, per consumare la porzione di cow . Per catturare la porzione in mezzo, si usa un gruppo di cattura (basta mettere la porzione di pattern che si desidera catturare tra parentesi):

 cow(.*)milk 

Non è necessario alcun lookheadhead.

Ecco una regex che afferra ciò che c’è tra mucca e latte (senza spazio iniziale / finale):

 srctext = "My cow always gives milk."; var re = /(.*cow\s+)(.*)(\s+milk.*)/; var newtext = srctext.replace(re, "$2"); 

Un esempio: http://jsfiddle.net/entropo/tkP74/

Espressione regolare per ottenere una stringa tra due stringhe in Javascript

La soluzione più completa che funzionerà nella maggior parte dei casi è l’utilizzo di un gruppo di acquisizione con un pattern di corrispondenza a punti pigri . Tuttavia, un punto . nella regex JS non corrispondono i caratteri di interruzione di riga, quindi, ciò che funzionerà nel 100% dei casi è un costrutto [^] o [\s\S] / [\d\D] / [\w\W] .

ECMAScript 2018 e una nuova soluzione compatibile

In ambienti JS che supportano ECMAScript 2018 , s modificatore s consente . per abbinare qualsiasi carattere, compresi i caratteri di interruzione di riga, e il motore regex supporta le schermate di lunghezza variabile. Quindi, puoi usare una regex come

 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 

In entrambi i casi, la posizione corrente viene controllata per cow con 1/0 o più spazi bianchi dopo la cow , quindi qualsiasi 0+ caratteri il più ansible ridotto viene abbinato e consumato (= aggiunto al valore della partita), e quindi il milk viene controllato per (con qualsiasi 1/0 o più spazi bianchi prima di questa sottostringa).

Scenario 1: input su linea singola

Questo e tutti gli altri scenari seguenti sono supportati da tutti gli ambienti JS. Vedi esempi di utilizzo in fondo alla risposta.

 cow (.*?) milk 

cow viene prima trovata, quindi uno spazio, quindi i caratteri 0+ tranne i caratteri di interruzione di riga, il meno ansible di *? è un quantificatore pigro, viene catturato nel Gruppo 1 e quindi deve seguire uno spazio con il milk (e anche quelli sono abbinati e consumati ).

Scenario 2: input multilinea

 cow ([\s\S]*?) milk 

Qui, la cow e uno spazio vengono abbinati per primi, quindi tutti i caratteri 0+ il meno ansible vengono abbinati e catturati nel Gruppo 1, quindi viene abbinato uno spazio con il milk .

Scenario 3: corrispondenze sovrapposte

Se hai una stringa come >>>15 text>>>67 text2>>> e hai bisogno di ottenere 2 corrispondenze tra >>> + number + whitespace e >>> , non puoi usare />>>\d+\s(.*?)>>>/g quanto questo troverà solo 1 incontro dovuto al fatto che il >>> prima di 67 è già consumato al momento della ricerca della prima corrispondenza. Puoi usare un lookahead positivo per controllare la presenza del testo senza effettivamente "ingarbugliarlo" (cioè accodandolo alla partita):

 />>>\d+\s(.*?)(?=>>>)/g 

Guarda la demo regex online che text1 e text2 come contenuti del gruppo 1 trovati.

Vedi anche Come ottenere tutte le possibili corrispondenze sovrapposte per una stringa .

Considerazioni sulle prestazioni

Pattern di corrispondenza dei punti pigri ( .*? ) All'interno dei pattern regex può rallentare l'esecuzione dello script se viene fornito un input molto lungo. In molti casi, la tecnica di srotolare il ciclo aiuta in misura maggiore. Cercando di afferrare tutto tra cow e milk da "Their\ncow\ngives\nmore\nmilk" , vediamo che dobbiamo solo abbinare tutte le linee che non iniziano con il milk , quindi, invece di cow\n([\s\S]*?)\nmilk possiamo usare:

 /cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm 

Guarda la demo regex (se può esserci \r\n , usa /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm ). Con questa piccola stringa di test, il guadagno di prestazioni è trascurabile, ma con un testo molto grande, sentirai la differenza (specialmente se le linee sono lunghe e le interruzioni di riga non sono molto numerose).

Esempio di utilizzo regex in 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); 
  • Devi catturare il .*
  • Puoi (ma non devi) rendere il .* concordato
  • Non c’è davvero bisogno di guardare avanti.

     > /cow(.*?)milk/i.exec('My cow always gives milk'); ["cow always gives milk", " always gives "] 

Sono stato in grado di ottenere ciò di cui avevo bisogno utilizzando la soluzione di Martinho Fernandes qui sotto. Il codice è:

 var test = "My cow always gives milk"; var testRE = test.match("cow(.*)milk"); alert(testRE[1]); 

Noterai che sto avvisando la variabile testRE come una matrice. Questo perché testRE sta tornando come array, per qualche motivo. L’output di:

 My cow always gives milk 

Cambia in:

 always gives 

Che dire solo usando la seguente espressione regolare:

 (?<=My cow\s).*?(?=\smilk) 

La risposta scelta non ha funzionato per me … hmm …

Basta aggiungere spazio dopo la mucca e / o prima del latte per tagliare gli spazi da “dà sempre”

 /(?<=cow ).*(?= milk)/ 

inserisci la descrizione dell'immagine qui

Il metodo match () cerca una stringa per una corrispondenza e restituisce un object Array.

 // Original string var str = "My cow always gives milk"; // Using index [0] would return
// "**cow always gives milk**" str.match(/cow(.*)milk/)**[0]** // Using index **[1]** would return // "**always gives**" str.match(/cow(.*)milk/)[1]