244 votes

Expression régulière pour obtenir une chaîne de caractères entre deux chaînes de caractères en Javascript

J'ai trouvé des messages très similaires, mais je n'arrive pas à trouver mon expression régulière.

J'essaie d'écrire une expression régulière qui renvoie une chaîne qui se trouve entre deux autres chaînes. Par exemple : Je veux obtenir la chaîne qui se trouve entre les chaînes "vache" et "lait".

Ma vache donne toujours du lait

renverrait

"donne toujours"

Voici l'expression que j'ai reconstituée jusqu'à présent :

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

Cependant, cette méthode renvoie la chaîne "la vache donne toujours".

244voto

R. Martinho Fernandes Points 96873

Un lookahead (qui (?= ) ne consomme pas d'intrants. Il s'agit d'un assertion de largeur nulle (tout comme les vérifications des limites et les contrôles a posteriori).

Vous voulez une correspondance régulière ici, pour consommer le cow portion. Pour capturer la partie intermédiaire, vous utilisez un groupe de capture (il suffit de mettre entre parenthèses la partie du motif que vous souhaitez capturer) :

cow(.*)milk

Aucune anticipation n'est nécessaire.

139voto

Wiktor Stribiżew Points 100073

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]));

57voto

entropo Points 1805

Voici une expression rationnelle qui permet de saisir ce qui se trouve entre la vache et le lait (sans espace avant/arrière) :

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

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

20voto

Matt Ball Points 165937
  • Vous devez capturer le .*
  • Vous pouvez (mais ce n'est pas obligatoire) faire le .* non réclamé
  • Il n'est vraiment pas nécessaire d'avoir une longueur d'avance.

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

20voto

duduwe Points 222

La réponse choisie n'a pas fonctionné pour moi...hmm...

Il suffit d'ajouter un espace après la vache et/ou avant le lait pour supprimer les espaces de " donne toujours ".

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

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X