Expression régulière pour obtenir une chaîne entre deux chaînes en JavaScript
La solution la plus complète qui fonctionnera dans la grande majorité des cas utilise un groupe de capture avec un modèle de correspondance de points paresseux . Cependant, un point .
dans l'expression régulière JavaScript ne correspond pas aux caractères de saut de ligne, donc, ce qui fonctionnera dans 100% des cas est une construction [^]
ou [\s\S]
/ [\d\D]
/ [\w\W]
.
ECMAScript 2018 et solution compatible plus récente
Dans les environnements JavaScript prenant en charge ECMAScript 2018 , le s
modificateur permet de .
faire correspondre n'importe quel caractère, y compris les caractères de saut de ligne, et le moteur regex prend en charge les lookbehinds de longueur variable. Donc, vous pouvez utiliser une expression régulière comme
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
Dans les deux cas, la position actuelle est vérifiée cow
avec n'importe quel 1/0 ou plus d'espaces blancs après cow
, puis tous les caractères 0+ aussi peu que possible sont mis en correspondance et consommés (= ajouté à la valeur de correspondance), puis milk
est vérifié (avec n'importe quel 1/0 ou plus d'espaces blancs avant cette sous-chaîne).
Scénario 1: entrée sur une seule ligne
Ce scénario et tous les autres scénarios ci-dessous sont pris en charge par tous les environnements JavaScript. Voir des exemples d'utilisation au bas de la réponse.
cow (.*?) milk
cow
se trouve d' abord, puis un espace, puis tout 0+ caractères autres que les caractères de saut de ligne, aussi peu que possible *?
est un quantificateur paresseux, sont capturés dans le Groupe 1, puis un espace avec milk
suivi incontournable (et ceux qui sont en correspondance et consommaient aussi ).
Scénario 2: entrée multiligne
cow ([\s\S]*?) milk
Ici, cow
et un espace est mis en correspondance en premier, puis tous les caractères 0+ aussi peu que possible sont mis en correspondance et capturés dans le groupe 1, puis un espace avec milk
sont mis en correspondance.
Scénario 3: correspondances qui se chevauchent
Si vous avez une chaîne comme >>>15 text>>>67 text2>>>
et que vous avez besoin d'obtenir 2 correspondances entre >>>
+ number
+ whitespace
et >>>
, vous ne pouvez pas l'utiliser />>>\d+\s(.*?)>>>/g
car cela ne trouvera qu'une seule correspondance car l' >>>
avant 67
est déjà consommé lors de la recherche de la première correspondance. Vous pouvez utiliser une anticipation positive pour vérifier la présence du texte sans réellement «l'avaler» (c'est-à-dire l'ajouter à la correspondance):
/>>>\d+\s(.*?)(?=>>>)/g
Voir la démo en ligne regex rendement text1
et du text2
groupe 1 contenus trouvés.
Consultez également Comment obtenir toutes les correspondances qui se chevauchent pour une chaîne .
Considérations relatives aux performances
Le motif de correspondance de points paresseux ( .*?
) à l'intérieur des modèles de regex peut ralentir l'exécution du script si une entrée très longue est donnée. Dans de nombreux cas, la technique du déroulement de la boucle aide dans une plus grande mesure. En essayant de saisir tout entre cow
et milk
depuis "Their\ncow\ngives\nmore\nmilk"
, nous voyons que nous avons juste besoin de faire correspondre toutes les lignes qui ne commencent pas par milk
, donc, au lieu de cow\n([\s\S]*?)\nmilk
nous pouvons utiliser:
/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm
Voir la démo regex (s'il y en a \r\n
, utilisez /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm
). Avec cette petite chaîne de test, le gain de performances est négligeable, mais avec du texte très volumineux, vous sentirez la différence (surtout si les lignes sont longues et les sauts de ligne peu nombreux).
Exemple d'utilisation de regex dans 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);
Utiliser la String#matchAll
méthode moderne
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]));