web-dev-qa-db-fra.com

Regex jusqu'à mais non compris

Pour regex, quelle est la syntaxe de recherche jusqu'à mais non incluse? Un peu comme:

Haystack:
The quick red fox jumped over the lazy brown dog

Expression:
.*?quick -> and then everything until it hits the letter "z" but do not include z
61
NoodleOfDeath

La façon explicite de dire "rechercher jusqu'à X mais sans inclure X" est la suivante:

(?:(?!X).)*

X peut être n'importe quelle expression régulière.

Dans votre cas, cependant, cela pourrait être exagéré - ici le moyen le plus simple serait

[^z]*

Cela correspondra à tout sauf z et s'arrêtera donc juste avant le prochain z.

Donc .*?quick[^z]* Correspondra à The quick fox jumps over the la.

Cependant, dès que vous avez plusieurs lettres simples à rechercher, (?:(?!X).)* Entre en jeu, par exemple

(?:(?!lazy).)* - correspond à tout jusqu'au début du mot lazy.

Ceci utilise un assertion de lookahead, plus spécifiquement un lookahead négatif.

.*?quick(?:(?!lazy).)* correspondra à The quick fox jumps over the.

Explication:

(?:        # Match the following but do not capture it:
 (?!lazy)  # (first assert that it's not possible to match "lazy" here
 .         # then match any character
)*         # end of group, zero or more repetitions.

En outre, lorsque vous recherchez des mots clés, vous pouvez les entourer d'ancres de délimitation Word: \bfox\b Ne correspondra qu'au mot complet fox mais pas au renard dans foxy.

Remarque

Si le texte à mettre en correspondance peut également inclure des sauts de ligne, vous devrez définir l'option "le point correspond à tout" de votre moteur d'expression régulière. Habituellement, vous pouvez y parvenir en ajoutant (?s) Au regex, mais cela ne fonctionne pas dans tous les moteurs de regex (notamment JavaScript).

Solution alternative:

Dans de nombreux cas, vous pouvez également utiliser une solution plus simple et plus lisible qui utilise un quantificateur paresseux. En ajoutant un ? Au quantificateur *, Il essaiera de faire correspondre le moins de caractères possible à partir de la position actuelle:

.*?(?=(?:X)|$)

correspondra à n'importe quel nombre de caractères, s'arrêtant juste avant X (qui peut être n'importe quelle expression régulière) ou la fin de la chaîne (si X ne correspond pas). Vous devrez peut-être également définir l'option "le point correspond à tout" pour que cela fonctionne. (Remarque: j'ai ajouté un groupe non capturant autour de X afin de l'isoler de manière fiable de l'alternance)

142
Tim Pietzcker

Une syntaxe regex anticipée peut vous aider à atteindre votre objectif. Ainsi, une expression régulière pour votre exemple est

.*?quick.*?(?=z)

Et il est important de noter le .*? correspondance paresseuse avant le (?=z) lookahead: l'expression correspond à une sous-chaîne jusqu'à ce qu'une première occurrence de la lettre z.

Voici un exemple de code C #:

const string text = "The quick red fox jumped over the lazy brown dogz";

string lazy = new Regex(".*?quick.*?(?=z)").Match(text).Value;
Console.WriteLine(lazy); // The quick red fox jumped over the la

string greedy = new Regex(".*?quick.*(?=z)").Match(text).Value;
Console.WriteLine(greedy); // The quick red fox jumped over the lazy brown dog
10
Igor Kustov

Essaye ça

(.*?quick.*?)z
0
Max