Expression régulière pour obtenir une chaîne de caractères entre deux chaînes de caractères en JavaScript
La solution la plus complète qui fonctionnera dans la grande majorité des cas est l'utilisation d'un groupe de capture avec un modèle d'assortiment de points paresseux . Toutefois, un point .
en JavaScript ne correspond pas aux caractères de retour à la ligne, donc ce qui fonctionnera dans 100% des cas est un [^]
o [\s\S]
/ [\d\D]
/ [\w\W]
des constructions.
Solution compatible avec ECMAScript 2018 et les versions plus récentes
Dans les environnements JavaScript prenant en charge ECMAScript 2018 , s
Le modificateur permet .
pour correspondre à n'importe quel caractère, y compris les caractères de retour à la ligne, et le moteur de regex prend en charge les lookbehinds de longueur variable. Vous pouvez donc utiliser une expression rationnelle telle que
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 pour cow
avec 1/0 ou plus d'espaces blancs après cow
puis tous les caractères 0+, aussi peu nombreux que possible, sont recherchés et consommés (= ajoutés à la valeur de la correspondance), et ensuite milk
est vérifiée (avec tout espace blanc 1/0 ou plus avant cette sous-chaîne).
Scénario 1 : Entrée monoligne
Ce scénario et tous les autres ci-dessous sont pris en charge par tous les environnements JavaScript. Voir les exemples d'utilisation au bas de la réponse.
cow (.*?) milk
cow
est trouvé en premier, puis un espace, puis tous les caractères 0+ autres que les caractères de retour à la ligne, aussi peu que possible en tant que *?
est un quantificateur paresseux, sont capturés dans le groupe 1, puis un espace avec milk
doivent suivre (et ceux-ci sont assortis et consommé ).
Scénario 2 : Entrée multiligne
cow ([\s\S]*?) milk
Ici, cow
et un espace sont recherchés en premier, puis tous les caractères 0+, aussi peu nombreux que possible, sont recherchés et capturés dans le groupe 1, et enfin un espace avec milk
sont appariés.
Scénario 3 : Chevauchement des correspondances
Si vous avez une chaîne de caractères comme >>>15 text>>>67 text2>>>
et vous devez obtenir 2 matches entre les deux >>>
+ number
+ whitespace
y >>>
vous ne pouvez pas utiliser />>>\d+\s(.*?)>>>/g
car il n'y aura qu'une seule correspondance du fait que l'élément >>>
avant 67
est déjà consommé après avoir trouvé la première allumette. Vous pouvez utiliser un perspectives d'avenir positives pour vérifier la présence du texte sans le "gober" (c'est-à-dire l'ajouter à la correspondance) :
/>>>\d+\s(.*?)(?=>>>)/g
Voir le Démonstration en ligne des expressions rationnelles cédant text1
y text2
en tant que contenu du groupe 1.
Voir aussi Comment obtenir toutes les correspondances possibles d'une chaîne de caractères qui se chevauchent ? .
Considérations sur les performances
Modèle de correspondance de points paresseux ( .*?
) dans les motifs d'expressions rationnelles peut ralentir l'exécution de script si l'entrée est très longue. Dans de nombreux cas, technique de déroulement de la boucle aide dans une plus large mesure. En essayant d'attraper tous les cow
y milk
de "Their\ncow\ngives\nmore\nmilk"
Nous constatons qu'il suffit de faire correspondre toutes les lignes qui ne commencent pas par milk
Ainsi, au lieu de cow\n([\s\S]*?)\nmilk
que nous pouvons utiliser :
/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm
Voir le Démonstration des expressions rationnelles (s'il peut y avoir \r\n
, utiliser /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm
). Avec cette petite chaîne de test, le gain de performance est négligeable, mais avec un texte très volumineux, vous sentirez la différence (surtout si les lignes sont longues et les retours à la ligne peu nombreux).
Exemple d'utilisation d'une expression rationnelle 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);
L'utilisation de la technologie moderne String#matchAll
méthode
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]));