2010-10-03 7 views
38

Pour regex quelle est la syntaxe pour la recherche jusqu'à mais ne comprend pas? Un peu comme:Regex jusqu'à ce que mais non compris

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 

Répondre

104

La façon explicite de dire "recherche jusqu'à X mais dont X" est:

(?:(?!X).)* 

X peut être une expression régulière.

Dans votre cas, cependant, cela pourrait être surpuissant - ici la meilleure façon serait

[^z]* 

Cela correspond tout sauf z et donc arrêter juste avant la prochaine z.

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

Cependant, dès que vous avez plus d'une lettre simple à chercher, (?:(?!X).)* entre en jeu, par exemple

(?:(?!lazy).)* - quoi que ce soit correspond jusqu'au début du mot lazy.

Ceci utilise un lookahead assertion, plus précisément une tête de lecture négative.

.*?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. 

De plus, lors de la recherche des mots-clés, vous pouvez les entourer de mot d'ancrage aux limites: \bfox\b ne correspondra le mot complet fox mais pas le renard dans foxy.

Remarque

Si le texte à apparier peut également inclure des sauts de ligne, vous devez définir l'option « point correspond à tous » de votre moteur de regex. Habituellement, vous pouvez y parvenir en ajoutant (?s) à la regex, mais cela ne fonctionne pas dans tous les moteurs regex (notamment JavaScript).

Autre solution:

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

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

correspond à tout nombre de caractères, s'arrêtant juste avant X (qui peut être une 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 «correspond à tous les points» pour que cela fonctionne.(Note: J'ai ajouté un groupe non-capture autour X afin d'isoler de manière fiable de l'alternance)

+0

+1 Vraiment belle réponse, ne fonctionne pas avec unfortunatly 'grep', mais cette [réponse] (http://stackoverflow.com/a/5979402/ 354831) fait. –

+0

@AlexandreLavoie: Intéressant. Pourquoi l'autre devrait-il fonctionner et pas celui-ci? Les deux utilisent des assertions lookahead. Peut-être est-ce juste à cause du groupe '(?: ...)' qui ne capture pas? Est-ce que ça marche avec '((?! X).) *'? –

+1

Vraiment je ne sais pas, je ne suis pas un expert en regex ni grep. J'utilisais 'grep' pour filtrer les requêtes pour une seule base de données de mysql bin transformet en sql. Voici la bête: 'grep -Po" (? S) utilise database_to_keep (. *?) (? =^Use) "mysql-bin.000045.sql> filtered.sql' –

0

Essayez cette

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

Cela inclut le" z "dans le match, qui est précisément ce que le demandeur veut éviter. Peut-être que l'expression régulière est destinée à être un terme dans un '|' alternative, et cette alternative regex est utilisée pour effectuer plusieurs correspondances. Si le "z" est le début d'une chaîne qui serait suivie d'un autre ** terme, alors cette correspondance sera perdue car le "z" est déjà utilisé par la correspondance en cours. –

5

Un lookahead regex syntax peut vous aider à atteindre votre objectif. Ainsi, un regex pour votre exemple est

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

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

Voici 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