2010-10-03 6 views
38

Für Regex, was ist die Syntax für die Suche bis, aber nicht einschließlich? Kinda mag:Regex bis einschließlich

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 

Antwort

104

Die explizite Art und Weise "bis X suchen, aber nicht einschließlich X" zu sagen ist:

(?:(?!X).)* 

wo X jeder regulärer Ausdruck sein kann.

In Ihrem Fall, obwohl, könnte dies zu viel des Guten - hier der einfachste Weg,

[^z]* 

wäre Dies alles außer z übereinstimmen und daher zu Recht vor dem nächsten z zu stoppen.

So .*?quick[^z]* wird übereinstimmen The quick fox jumps over the la.

jedoch, sobald Sie mehr als ein einfacher Brief haben zu achten ist, kommt (?:(?!X).)* ins Spiel, zum Beispiel

(?:(?!lazy).)* - lazy alles bis zum Beginn des Wortes entsprechen.

Dies ist mit einem lookahead assertion, genauer gesagt eine negative Lookahead.

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

Erläuterung:

(?:  # 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. 

Wenn darüber hinaus für Keywords suchen, können Sie sie mit Wortgrenze Anker umgeben: \bfox\b wird passen nur das komplette Wort fox aber nicht den Fuchs in foxy.

Hinweis

Wenn der Text auch angepasst werden können Zeilenumbrüche enthalten, müssen Sie die Möglichkeit, Ihre Regex-Engine, um „Punkt alle Matches“. Normalerweise können Sie dies erreichen, indem Sie (?s) der Regex voranstellen, aber das funktioniert nicht in allen Regex-Engines (insbesondere JavaScript).

Alternative Lösung:

In vielen Fällen können Sie auch eine einfachere, besser lesbare Lösung verwenden, die einen faulen Quantifizierer verwendet. eine ? zum * quantifier Durch das Hinzufügen, wird es versuchen, so wenig Zeichen wie möglich von der aktuellen Position zum Spiel:

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

beliebige Anzahl von Zeichen übereinstimmen, stoppen kurz vor X (was jede Regex sein kann) oder das Ende der Zeichenfolge (wenn X nicht übereinstimmt). Möglicherweise müssen Sie auch die Option "dot matches all" setzen, damit dies funktioniert.(Anmerkung: Ich habe eine nicht-einfangende Gruppe um X hinzugefügt, um zuverlässig aus dem Wechsel zu isolieren)

+0

+1 Wirklich nette Antwort, funktioniert leider nicht mit 'grep', aber die [Antwort] (http://stackoverflow.com/a/5979402/ 354831) tut. –

+0

@AlexandreLavoie: Interessant. Warum sollte der andere arbeiten und nicht dieser? Beide verwenden Lookahead-Assertions. Vielleicht liegt es nur an der "(?: ...)" nicht einfangenden Gruppe? Funktioniert es mit '((?! X).) *'? –

+1

Wirklich weiß nicht, ich bin kein Regex-Experte noch grep. Ich benutzte 'grep', um Anfragen für nur eine Datenbank von mysql bin transformet in sql zu filtern. Hier ist das Biest: 'grep -Po '(? S) benutze database_to_keep (. *?) (? =^Benutze)" mysql-bin.000045.sql> filtered.sql' –

0

Versuchen Sie, diese

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

Dazu gehört das "z" in der Übereinstimmung, die Genau das will der Fragesteller vermeiden. Vielleicht ist die Regex ein Begriff in einem '|' Alternative, und diese alternative Regex wird verwendet, um mehrere Übereinstimmungen durchzuführen. Wenn das "z" der Anfang einer Zeichenfolge ist, die in der Alternative mit einem ** anderen Begriff übereinstimmt, wird diese Übereinstimmung verwirkt, da das "z" bereits von der aktuellen Übereinstimmung verbraucht wird. –

5

A lookahead regex syntax können Sie Ihr Ziel erreichen helfen. So wird eine Regex für Ihr Beispiel ist

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

Und es ist wichtig, den .*? faul Matching vor dem (?=z) Look-Ahead zu bemerken: Der Ausdruck paßt einen Teil bis ein ersten Auftreten des z Briefes.

ist hier # Codebeispiel 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 
Verwandte Themen