2009-05-20 10 views
4

Lange Rede, kurzer Sinn, ich habe zwei Regex-Muster. Ein Muster stimmt mit Dingen überein, die ich ersetzen möchte, und das andere Muster entspricht einem speziellen Fall jener Muster, die nicht ersetzt werden sollten. Stellen Sie sich für ein einfaches Beispiel vor, dass das erste "\ {. * \}" Und das zweite "\ {\ {. * \} \}" Ist. Dann sollte "{this}" ersetzt werden, aber "{{this}}" sollte nicht ersetzt werden. Gibt es eine einfache Möglichkeit, eine Zeichenfolge zu nehmen und zu sagen "ersetzen Sie alle Instanzen der ersten Zeichenfolge mit" Hallo ", solange es nicht mit der zweiten Zeichenfolge übereinstimmt"?Eine Regex nur dann ersetzen, wenn sie nicht mit einer anderen Regex (Python) übereinstimmt

Mit anderen Worten, gibt es eine Möglichkeit, eine Regex, die "die erste Zeichenfolge entspricht, aber nicht die zweite" leicht ohne die erste Zeichenfolge ändern? Ich weiß, dass ich meine erste Regex von Hand ändern könnte, um nie Instanzen der zweiten zu finden, aber wenn die erste Regex komplexer wird, wird das sehr schwierig.

Antwort

4

können Sie geben eine Funktion ersetzen (reference)

Aber stellen Sie sicher, dass die erste Regex die zweite enthalten. Dies ist nur ein Beispiel:

regex1 = re.compile('\{.*\}') 
regex2 = re.compile('\{\{.*\}\}') 

def replace(match): 
    match = match.group(0) 
    if regex2.match(match): 
     return match 
    return 'replacement' 


regex1.sub(replace, data) 
1

Sie können alle {} -Instanzen durch Ihre Ersetzungszeichenfolge ersetzen (einschließlich der {{}}) und dann die {{}} -Einheiten durch eine Rückreferenz auf sich selbst ersetzen (überschreiben der ersten Ersetzung durch die ursprünglichen Daten) - dann hätten sich nur die {} Instanzen geändert.

+0

Können Sie mir ein Beispiel geben, wie man das in Python macht? Ich bin mir nicht ganz sicher, ob ich das verstehe. Vielen Dank! – So8res

+0

Ich kann in etwa einer Stunde, aber nicht gerade jetzt, tut mir leid ... –

0

Es kommt mir suboptimalen gegen zwei verschiedene reguläre Ausdrücke passen, wenn, was Sie suchen wirklich ein Muster ist. Zur Veranschaulichung:

import re 
foo = "{{this}}" 
bar = "{that}" 
re.match("\{[^\{].*[^\}]\}", foo) # gives you nothing 
re.match("\{[^\{].*[^\}]\}", bar) # gives you a match object 

So ist es wirklich Ihre Regex, die ein bisschen genauer sein könnte.

+0

Das stimmt, aber Nate gab ein einfaches imaginäres Beispiel. Es ist nicht immer der Fall. –

6

Mit negativem Vorgriff/hinter Behauptung

pattern = re.compile("(?<!\{)\{(?!\{).*?(?<!\})\}(?!\})") 
pattern.sub("hello", input_string) 

Negativer Vorgriff/hinter Behauptung können Sie gegen mehr des Zeichenfolge vergleichen, ist aber nicht so mit bis Teil der Zeichenfolge für das Spiel betrachtet . Es gibt auch eine normale Look-ahead-/hinter-Assertion, die bewirkt, dass die Zeichenkette nur dann übereinstimmt, wenn die Zeichenkette dem gegebenen Muster folgt/vorangeht.

Das ist ein bisschen verwirrend sucht, hier ist es in Stücke:

"(?<!\{)" #Not preceded by a { 
"\{"  #A { 
"(?!\{)" #Not followed by a { 
".*?"  #Any character(s) (non-greedy) 
"(?<!\})" #Not preceded by a } (in reference to the next character) 
"\}"  #A } 
"(?!\})" #Not followed by a } 

So sind wir {ohne weitere { 's drum herum, gefolgt von einigen Zeichen für eine Suche, gefolgt von einem} ohne irgendwelche anderen} ist darum herum.

Durch die Verwendung negativer Look-Ahead-/Behind-Assertion, verdichten wir es auf einen einzelnen regulären Ausdruck, der nur einzelne {} 's irgendwo in der Zeichenfolge erfolgreich abgleicht.

Beachten Sie auch, dass * ein gieriger Operator ist. Es wird so viel wie möglich zusammenpassen. Wenn Sie "\{.*\}" verwenden und es mehr als einen {} Block im Text gibt, wird alles dazwischen mitgenommen.

"Dies ist ein Beispieltext {block1} mehr Text, sehen Sie mich verschwinden {block2} noch mehr Text"

wird

„Dies ist ein Beispieltext hallo noch mehr text“

statt

„Dies ist ein Beispieltext hallo mehr Text, schau mir noch mehr Text verschwinden Hallo“

Um den richtigen Ausgang wir es nicht gierig machen, indem ein anhängen? Bekommen müssen.

Die Python-Dokumente können die re-Bibliothek gut darstellen, aber die einzige Möglichkeit, wirklich zu lernen, ist Experimentieren.

Verwandte Themen