2013-03-02 7 views
20

Ich kann diesen Code unten verwenden, um eine neue Datei mit der Ersetzung von a mit aa unter Verwendung von regulären Ausdrücken zu erstellen.Wie kann ich mehrere Substitutionen mit Regex in Python tun?

import re 

with open("notes.txt") as text: 
    new_text = re.sub("a", "aa", text.read()) 
    with open("notes2.txt", "w") as result: 
     result.write(new_text) 

Ich frage mich, kann ich diese Zeile zu verwenden, new_text = re.sub("a", "aa", text.read()), mehrere Male, aber die Zeichenfolge für die anderen Buchstaben zu ersetzen, die ich um ändern wollen mehr als einen Buchstaben in meinem Text zu ändern?

Das heißt, so a ->aa, b ->bb und c ->cc.

Also muss ich diese Zeile für alle Buchstaben schreiben, die ich ändern möchte oder gibt es einen einfacheren Weg. Vielleicht um ein "Wörterbuch" für Übersetzungen zu erstellen. Soll ich diese Buchstaben in ein Array einfügen? Ich bin mir nicht sicher, wie ich sie anrufen soll, wenn ich es tue.

Antwort

27

Die von @nhahtdh vorgeschlagene Antwort ist gültig, aber ich würde weniger pythonisch argumentieren als das kanonische Beispiel, das Code weniger undurchsichtig als seine Regex verwendet Manipulationen und nutzt die integrierten Datenstrukturen von Python und die anonyme Funktion.

Ein Wörterbuch der Übersetzungen ist in diesem Zusammenhang sinnvoll. In der Tat, das ist, wie das Python-Kochbuch macht es, wie

gezeigt in diesem Beispiel (kopiert von Activestate http://code.activestate.com/recipes/81330-single-pass-multiple-replace/)
import re 

def multiple_replace(dict, text): 
    # Create a regular expression from the dictionary keys 
    regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys()))) 

    # For each match, look-up corresponding value in dictionary 
    return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text) 

if __name__ == "__main__": 

    text = "Larry Wall is the creator of Perl" 

    dict = { 
    "Larry Wall" : "Guido van Rossum", 
    "creator" : "Benevolent Dictator for Life", 
    "Perl" : "Python", 
    } 

    print multiple_replace(dict, text) 

Also in Ihrem Fall könnten Sie einen dict trans = {"a": "aa", "b": "bb"} machen und es dann in multiple_replace passieren zusammen mit dem Text du willst übersetzt werden. Im Grunde besteht diese Funktion nur darin, einen riesigen Regex zu erstellen, der alle zu übersetzenden Regexes enthält, und wenn eine gefunden wird, übergibt man eine Lambda-Funktion an regex.sub, um das Wörterbuch nachschlagen zu können.

Sie diese Funktion nutzen zu können, während aus der Datei zu lesen, zum Beispiel:

with open("notes.txt") as text: 
    new_text = multiple_replace(replacements, text.read()) 
with open("notes2.txt", "w") as result: 
    result.write(new_text) 

ich eigentlich genau dieses Verfahren in der Produktion verwendet habe, in einem Fall, in dem ich die Monate des Jahres zu übersetzen brauchte aus Tschechisch ins Englische für eine Web Scraping Aufgabe. Wie @nhahtdh bemerkte, ist ein Nachteil dieses Ansatzes, dass er nicht frei von Präfixen ist: Dictionary-Schlüssel, die Präfixe anderer Dictionary-Schlüssel sind, führen zum Bruch der Methode.

+0

Wow danke ist ziemlich genau das, was ich gesucht habe. Ich habe noch eine grundlegende Frage, wie ignoriere ich Großbuchstaben? Wenn ich also A hätte und ich das auch in aa übersetzen wollte, ohne es dem Wörterbuch hinzuzufügen. – Euridice01

+0

@ Euridice01: Wenn Sie die Groß- und Kleinschreibung ignorieren möchten, geben Sie 're.I' in' re.compile' an. – nhahtdh

+0

Ihre aktuelle Lösung ist noch nicht für den Anwendungsfall konfiguriert, in dem ein Wortpaar existiert, von denen eines das Präfix des anderen ist. Die Reihenfolge des Auftretens im Wechsel ist von Bedeutung. Ich denke, zumindest sollten Sie diese Annahme angeben. – nhahtdh

12

können Sie erfassen verwenden Gruppe und Rückreferenzierung:

re.sub(r"([characters])", r"\1\1", text.read()) 

Put Zeichen, die Sie zwischen [] verdoppeln wollen. Für den Fall von Kleinschreibung a, b, c:

re.sub(r"([abc])", r"\1\1", text.read()) 

Im Ersatzzeichenfolge können Sie unabhängig von einer Erfassungsgruppe () mit \n Schreibweise angepasst verweisen, wo n einige positive ganze Zahl ist (0 ausgeschlossen) . \1 bezieht sich auf die erste einfangende Gruppe. Es gibt eine andere Notation \g<n>, wobei n eine beliebige nicht negative Ganzzahl sein kann (0 erlaubt); \g<0> bezieht sich auf den gesamten Text, auf den der Ausdruck passt.


Wenn Sie alle Zeichen außer neue Linie zu verdoppeln:

re.sub(r"(.)", r"\1\1", text.read()) 

Wenn Sie alle Zeichen verdoppeln wollen (neue Zeile enthalten):

re.sub(r"(.)", r"\1\1", text.read(), 0, re.S) 
1

Tipps Verwendung von how to make a 'stringy' class können wir ein Objekt identisch mit einem String machen, aber für eine zusätzliche sub Methode:

import re 
class Substitutable(str): 
    def __new__(cls, *args, **kwargs): 
    newobj = str.__new__(cls, *args, **kwargs) 
    newobj.sub = lambda fro,to: Substitutable(re.sub(fro, to, newobj)) 
    return newobj 

Dies ermöglicht es den Erbauer Muster zu verwenden, die schöner aussieht, funktioniert aber nur für eine Pre - bestimmte Anzahl von Substitutionen. Wenn Sie es in einer Schleife verwenden, ist es sinnlos, eine zusätzliche Klasse zu erstellen. Z.B.

>>> h = Substitutable('horse') 
>>> h 
'horse' 
>>> h.sub('h', 'f') 
'forse' 
>>> h.sub('h', 'f').sub('f','h') 
'horse' 
0

Ich fand ich hatte Emmett J. Butler Code zu ändern, indem die Lambda-Funktion verwenden myDict.get (mo.group (1), mo.group (1)). Der ursprüngliche Code funktionierte nicht für mich; myDict.get() bietet auch den Vorteil eines Standardwerts, wenn ein Schlüssel nicht gefunden wird.

OIDNameContraction = { 
           'Fucntion':'Func', 
           'operated':'Operated', 
           'Asist':'Assist', 
           'Detection':'Det', 
           'Control':'Ctrl', 
           'Function':'Func' 
} 

replacementDictRegex = re.compile("(%s)" % "|".join(map(re.escape, OIDNameContraction.keys()))) 

oidDescriptionStr = replacementDictRegex.sub(lambda mo:OIDNameContraction.get(mo.group(1),mo.group(1)), oidDescriptionStr) 
Verwandte Themen