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)
+1 Wirklich nette Antwort, funktioniert leider nicht mit 'grep', aber die [Antwort] (http://stackoverflow.com/a/5979402/ 354831) tut. –
@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).) *'? –
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' –