2012-12-06 4 views
27

Ich mache einige Text Normalisierung mit Python und regulären Ausdrücken. Ich möchte alle 'U' oder 'U' durch 'Sie' ersetzen. Hier ist, was ich bisher getan haben:Python re(): Wie man alle 'u' oder 'U' mit 'Sie' ersetzt

import re 
text = 'how are u? umberella u! u. U. [email protected] U# u ' 
print re.sub (' [u|U][s,.,?,!,W,#,@ (^a-zA-Z)]', ' you ', text) 

Der Ausgang ich erhalte, ist:

how are you you berella you you you you you you 

Wie Sie das Problem sehen kann, ist, dass ‚umberella‘ geändert zu ‚berella‘. Auch ich möchte den Charakter behalten, der nach einem "u" erscheint. Zum Beispiel möchte ich 'du!' in "du!" geändert werden. Kann mir jemand sagen, was ich falsch mache und was ist der beste Weg, um den regulären Ausdruck zu schreiben?

Antwort

48

Erstens, warum funktioniert Ihre Lösung nicht? Sie vermischen viele Konzepte. Meistens character class mit anderen. In der ersten Zeichenklasse verwenden Sie |, die von alternation stammt. In Zeichenklassen brauchen Sie die Pipe nicht. Listen Sie einfach alle Zeichen (und Zeichenbereiche) Sie wollen:

[Uu] 

Oder einfach schreiben u, wenn Sie die Groß- und Kleinschreibung Modifikator. Wenn Sie dort eine Pipe schreiben, wird die Zeichenklasse tatsächlich den Pipes in Ihrer Betreff-Zeichenfolge entsprechen.

Jetzt in der zweiten Zeichenklasse verwenden Sie das Komma, um Ihre Zeichen aus irgendeinem seltsamen Grund zu trennen. Dazu gehören auch Kommas in die matchbaren Zeichen. s und W sind wahrscheinlich die eingebauten Zeichenklassen. Dann entkomme ihnen! Andernfalls werden sie nur literal s und Literal W übereinstimmen. Aber dann \W enthält bereits alles, was Sie dort aufgeführt, so eine \W allein (ohne eckige Klammern) wäre genug gewesen. Und der letzte Teil (^a-zA-Z) funktioniert auch nicht, weil es einfach ^, (, ) und alle Buchstaben in die Zeichenklasse enthält. Die Negationssyntax funktioniert nur für ganze Zeichenklassen wie [^a-zA-Z].

Was Sie eigentlich wollen, ist zu behaupten, dass es keinen Brief vor oder nach Ihrer u gibt. Sie können dafür lookarounds verwenden. Der Vorteil besteht darin, dass sie nicht in das Spiel einbezogen werden und somit nicht entfernt werden:

r'(?<![a-zA-Z])[uU](?![a-zA-Z])' 

Bitte beachte, dass ich eine rohe Zeichenfolge verwendet. Ist in der Regel eine gute Übung für reguläre Ausdrücke, um Probleme mit Escape-Sequenzen zu vermeiden.

Dies sind negative Lookarounds, die sicherstellen, dass vor oder nach Ihrem u kein Buchstabe vorhanden ist. Dies ist ein wichtiger Unterschied zu der Behauptung, dass es ein Nicht-Buchstaben-Zeichen gibt (das ähnlich zu dem ist, was Sie getan haben), weil der letztere Ansatz nicht am Anfang oder Ende der Zeichenkette funktioniert.

Natürlich können Sie die Leerzeichen um you aus der Ersatzzeichenfolge entfernen.

Wenn Sie nicht u ersetzen mögen, die Ziffern nächsten sind, können Sie einfach die Ziffern in die Zeichenklassen sind:

r'(?<![a-zA-Z0-9])[uU](?![a-zA-Z0-9])' 

Und wenn aus irgendeinem Grunde ein benachbarter Strich würde auch disqualifizieren Ihre u für den Ersatz könnten Sie das ebenfalls einschließen. Aber dann fällt die Zeichenklasse mit dem eingebauten in \w:

r'(?<!\w)[uU](?!\w)' 

Welche ist, in diesem Fall entspricht EarlGray des r'\b[uU]\b'.

Wie oben erwähnt, können Sie alle verkürzen, indem Sie den Modifikator ohne Berücksichtigung der Groß- und Kleinschreibung verwenden. Unter dem ersten Ausdruck als Beispiel:

re.sub(r'(?<![a-z])u(?![a-z])', 'you', text, flags=re.I) 

oder

re.sub(r'(?<![a-z])u(?![a-z])', 'you', text, flags=re.IGNORECASE) 

je nach Ihren Wünschen.

Ich schlage vor, dass Sie das Tutorial lesen, das ich in dieser Antwort mehrmals verlinkt habe. Die Erklärungen sind sehr umfassend und sollten Ihnen einen guten Einstieg in die regulären Ausdrücke geben, denen Sie wahrscheinlich früher oder später wieder begegnen werden.

+2

Ihre Antwort war hervorragend. Vielen Dank! – user823743

+0

Dies ist eine interessante allgemeine Technik, aber ich würde lieber \ b verwenden, um einen Wortbruch zu entsprechen –

+2

@Sam Ich wollte nur sicherstellen, dass die Auswirkungen der Verwendung von '\ b' klar waren (insbesondere, dass Ziffern und Unterstriche sind im Lieferumfang enthalten). –

11

Verwenden Sie ein Sonderzeichen \b, die am Anfang oder am Ende eines Wortes leeren Zeichenfolge entspricht:

print re.sub(r'\b[uU]\b', 'you', text) 

Räume sind nicht eine zuverlässige Lösung, denn es gibt auch viele andere Satzzeichen sind, so dass ein Das abstrakte Zeichen \b wurde erfunden, um den Anfang oder das Ende eines Wortes anzuzeigen.

+2

außer dass ' '\ b'' ist die gleiche wie'' \ x08''. Du musst fliehen ('' \\ b'' oder 'r '\ b'')! – mata

+1

Dies ist die Ausgabe Ihres Codes auf 'Text' wie ich im Code definiert: Wie geht es dir? Umberella du! u. U. U @ U # u So keiner der U wurde zu dir geändert. – user823743

+1

@ user823743 Ja, ich vergesse 'r' vor meinem regulären Ausdruck, da es von Woble bearbeitet wurde (danke!). –

0

Eine andere mögliche Lösung kam ich mit war:

re.sub(r'([uU]+(.)?\s)',' you ', text)