Regulärer Ausdruck, um eine Zeichenfolge zwischen zwei Zeichenfolgen in JavaScript abzurufen
Die vollständigste Lösung, die in den allermeisten Fällen funktioniert, ist die Verwendung einer Erfassungsgruppe mit einem Lazy Dot Matching-Muster . Ein Punkt .in JavaScript-Regex stimmt jedoch nicht mit Zeilenumbruchzeichen überein. In 100% der Fälle funktioniert also ein [^]oder [\s\S]/ [\d\D]/ [\w\W]Konstrukt.
ECMAScript 2018 und neuere kompatible Lösung
In JavaScript-Umgebungen, die ECMAScript 2018 unterstützen , können mit dem sModifikator .alle Zeichen einschließlich Zeilenumbruchzeichen abgeglichen werden, und die Regex-Engine unterstützt Lookbehinds mit variabler Länge. Sie können also einen regulären Ausdruck wie verwenden
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 beiden Fällen wird die aktuelle Position cowmit 1/0 oder mehr Leerzeichen danach überprüft cow, dann werden alle 0+ Zeichen so wenig wie möglich abgeglichen und verbraucht (= zum Übereinstimmungswert hinzugefügt) und dann milküberprüft (mit einem beliebigen) 1/0 oder mehr Leerzeichen vor diesem Teilstring).
Szenario 1: Einzeilige Eingabe
Dieses und alle anderen unten aufgeführten Szenarien werden von allen JavaScript-Umgebungen unterstützt. Siehe Verwendungsbeispiele am Ende der Antwort.
cow (.*?) milk
cowzuerst, dann ein Leerzeichen, dann alle 0+ Zeichen außer Zeilenumbruch Zeichen, so wenig wie möglich zu finden ist wie *?ein fauler quantifier ist, werden in Gruppe 1 erfasst und dann ein Raum mit milkfolgen müssen (und die aufeinander abgestimmt sind und verbraucht auch ).
Szenario 2: Mehrzeilige Eingabe
cow ([\s\S]*?) milk
Hier wird zuerst cowein Leerzeichen abgeglichen, dann werden möglichst wenige 0+ Zeichen abgeglichen und in Gruppe 1 erfasst, und dann wird ein Leerzeichen mit milkabgeglichen.
Szenario 3: Überlappende Übereinstimmungen
Wenn Sie eine Zeichenfolge wie >>>15 text>>>67 text2>>>und Sie müssen zwei Spiele bekommen in-zwischen >>>+ number+ whitespaceund >>>können Sie nicht verwenden , />>>\d+\s(.*?)>>>/gda dies nur ein Spiel aufgrund der Tatsache , finden die >>>zuvor 67bereits verbraucht bei der Suche nach der ersten Partie. Sie können einen positiven Lookahead verwenden , um die Textpräsenz zu überprüfen, ohne sie tatsächlich zu "verschlingen" (dh an das Spiel anzuhängen):
/>>>\d+\s(.*?)(?=>>>)/g
Siehe die Online-Regex-Demo mit text1undtext2 als Gruppe 1 Inhalte.
Siehe auch So erhalten Sie alle möglichen überlappenden Übereinstimmungen für eine Zeichenfolge .
Leistungsüberlegungen
Lazy Dot Matching Pattern ( .*?) in Regex-Mustern kann die Skriptausführung verlangsamen, wenn sehr lange Eingaben gemacht werden. In vielen Fällen hilft die Unroll-the-Loop-Technik in größerem Maße. Beim Versuch, alle zwischen cowund milkvon zu erfassen "Their\ncow\ngives\nmore\nmilk", sehen wir, dass wir nur alle Zeilen abgleichen müssen, die nicht mit beginnen. Daher können wir milkstattdessen cow\n([\s\S]*?)\nmilkFolgendes verwenden:
/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm
Siehe die Regex-Demo (falls vorhanden \r\n, verwenden /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm). Mit dieser kleinen Testzeichenfolge ist der Leistungsgewinn vernachlässigbar, aber bei sehr großem Text werden Sie den Unterschied spüren (insbesondere wenn die Zeilen lang und die Zeilenumbrüche nicht sehr zahlreich sind).
Beispiel für die Verwendung von 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);
Mit der modernen String#matchAllMethode
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]));