2016-08-03 15 views
3

Ich versuche, eine Python-Funktion zu schreiben, die Instanzen von Text mit geschweiften Klammern mit dem Inhalt der geschweiften Klammern ersetzt, während leere Klammerpaare allein lassen. Zum Beispiel:Python Regex - Ersetzen Klammertext mit dem Inhalt der Klammern

foo {} bar {baz} würde foo {} bar baz werden.

Das Muster, das ich zu diesem Zweck erstellt habe, ist {[^{}]+}, d. H. Ein Text, der keine geschweiften Klammern enthält (um überlappende Übereinstimmungen zu vermeiden), die von geschweiften Klammern umgeben sind.

Die offensichtliche Lösung ist re.sub mit meinem Muster zu verwenden, und ich habe festgestellt, dass ich den gefundenen Text mit \g<0> verweisen kann:

>>> re.sub("{[^{}]+}", "A \g<0> B", "foo {} bar {baz}") 
'foo {} bar A {baz} B' 

kein Problem Also das ist. Ich bin jedoch fest, wie Sie die Klammern aus dem referenzierten Text trimmen. Wenn ich versuche, einen Bereich auf den Ersatz-String Anwendung:

>>> re.sub("{[^{}]+}", "\g<0>"[1:-1], "foo{}bar{baz}") 
'foo{}barg<0' 

Der Bereich vor den \g<0> angewandt wird auf den gefundenen Text aufgelöst, und es trimmt die führenden \ und > Hinter, so dass nur g<0, die keine speziellen hat Bedeutung.

Ich habe versucht, die Definition auch eine Funktion, um die Trimmung auszuführen:

def trimBraces(string): 
    return string[1:-1] 

aber wenig überraschend, dass nichts geändert hat.

>>> re.sub("{[^{}]+}", trimBraces("\g<0>"), "foo{}bar{baz}") 
'foo{}barg<0' 

Was fehlt mir hier? Vielen Dank im Voraus.

Antwort

2

können Sie verwenden, um eine Erfassung Gruppe einen Teil des Spiels zu ersetzen:

>>> re.sub(r"{([^{}]+)}", r"\1", "foo{}bar{baz}") 
'foo{}barbaz' 
>>> re.sub(r"{([^{}]+)}", r"\1", "foo {} bar {baz}") 
'foo {} bar baz' 
+0

Einfach, funktioniert. Vielen Dank! – halbrd

2

Wenn Sie "\g<0>"[1:-1] als Ersatz Muster verwenden, müssen Sie nur die "\g<0>"String in Scheiben schneiden, nicht der tatsächliche Wert dieses Rückreferenz bezieht sich auf.

Wenn Sie Ihre „Trimmen“ Ansatz zu verwenden, müssen Sie das Spiel Datenobjekt zu dem re.sub weitergeben müssen:

this Python demo
re.sub("{[^{}]+}", lambda m: m.group()[1:-1], "foo{}bar{baz}") 
# => foo{}barbaz 

See. Beachten Sie, dass m.group() für die \g<0> in Ihrem Muster steht, d. H. Den gesamten Übereinstimmungswert.

Jedoch, mit capturing groups ist eine "organische" Lösung, siehe alexce's solution.

+1

Danke für die zusätzlichen Informationen. Es ist immer gut, die Konzepte zu verstehen, nicht nur zu wissen, was funktioniert :) – halbrd

+1

Beachten Sie, dass diese Lösung gut ist, wenn Sie eine bekannte Anzahl von Zeichen aus einer Zeichenfolge mit komplexeren Regex-Mustern mit Änderungen trimmen wollen (was ein schöner Ersatz wäre) für eine Funktion zum Zurücksetzen eines fehlenden Zweiges in Python 're'). Angenommen, Sie müssen Teilstrings wie "..." oder "..." oder "[....]" (nicht aber "[..."] oder "...." ') und ersetzen Sie mit, was innerhalb dieser Begrenzer ist. In Python 2.x, 're.Sub "wird Probleme mit dem Backreference-Ansatz haben. Python 3.5 're' handhabt das,' print (re (r '"([^"] *) "| \' ([^ \ '] *) \' ', r' \ 1 \ 2 '," 'Something' "))' 'Something'' in Python 3.5.1. –