2017-11-06 1 views
0

Der StringPython: string & Liste re.sub Vergleich

txt = "this is a red house" 

hat entstanden. Und dann gibt es eine Liste

patterns = ["thi", "a r", "use"] 

mit einigen Übereinstimmungen dafür.

Der Plan war a = re.sub("".join(patterns), "".join(patterns) + "^", txt) zu verwenden, was ich gehofft als thi^s zurückkehren würde, ist ein r^^ ed Haus. Nicht so sehr - es druckt nur die Zeichenfolge wieder. Wenn stattdessen re.search verwendet wird, gibt es tatsächlich None zurück, der Grund ist, dass re.sub nichts findet, einfach die Zeichenfolge zurückgibt.

Ich war bereit, die Stecker auf diese zu ziehen, zu denken, dass re.sub kann einfach nicht so, wie ich es könnte dachte, verwendet werden, und dann habe ich versucht, es aus Versehen in einer einfachen Schleife:

for i in patterns: 
    a = re.sub(i, i + "^", txt) 
    print(a) 

Und plötzlich es (fast) gearbeitet: thi^s ein rotes Haus [\ n] dies ar^ed Haus [\ n] dies ist ein rotes Haus^. Jetzt kann ich es nicht einfach gehen lassen. Was ist los?

+0

Was genau ist Ihre Frage? –

+0

Zuerst würde ich herausfinden, wie eine funktionierende Regex aussehen sollte, bevor ich sie dynamisch konstruiere. Ihr Aufruf an 're' erzeugt die ursprüngliche Eingabe, weil Ihre konstruierte Regex keiner übereinstimmt, also wird nichts ersetzt. – Blender

+0

Sie sehen, das ist, was ich dachte. Und dann stimmte es in der Schleife überein. Wenn die konstruierte Regex nichts zusammenbringt, warum funktioniert sie dort? –

Antwort

2

Ihre Schleife vollständig behoben werden können, wenn Sie a mit txt ersetzen:

for i in patterns: 
    txt = re.sub(i, i + "^", txt) 
    print(txt) 

Auf diese Weise, die Sie tatsächlich den Text schrittweise durchführen, anstatt jede Substitution auf den ursprünglichen Text ändern und das Ergebnis zu verwerfen:

this is a red house 
thi^s is a red house 
thi^s is a r^ed house 
thi^s is a r^ed house^ 

Da Sie wirklich nicht einen regulären Ausdruck in re.sub() verwenden, würde es einfacher sein, nur str.replace verwenden:

for pattern in patterns: 
    txt = txt.replace(pattern, pattern + '^') 

Wenn Sie tatsächlich reguläre Ausdrücke verwenden möchten, würden Sie so etwas zu tun haben:

patterns_regex = '(' + '|'.join(patterns) + ')' # ['a', 'b'] -> '(a|b)' 
print(re.sub(patterns_regex, r'\1^', txt) 
1

Verbinden Sie Ihre Muster zusammen mit |, dann eine Funktion als Ersatz Argument von re.sub() verwenden:

regex = re.compile("|".join([f"({p})" for p in patterns])) 
regex.sub(lambda m: m.string[m.start():m.end()]+"^", txt) 

# 'thi^s is a r^ed house^' 

Hinweis: Wenn Sie nicht re.compile() verwenden wollen, können Sie alles in einer Zeile tun mit :

re.sub("|".join([f"({p})" for p in patterns]), 
     lambda m: m.string[m.start():m.end()]+"^", 
     txt) 
1

Sie speichern die Ersetzungen nicht bei jeder Iteration Ihrer for-Schleife. Versuchen Sie, den ersetzten Wert wieder an txt zu übertragen.

import re 

txt = "this is a red house" 
patterns = ["thi", "a r", "use"] 

for i in patterns: 
    txt = re.sub(i, i + "^", txt) 
print(txt) 
# prints: 
thi^s is a r^ed house^ 
2

Dies gibt Ihnen das Ergebnis Sie suchen:

txt = "this is a red house" 
patterns = ["thi", "a r", "use"] 

for s in patterns: 
    txt = re.sub(s,s+'^',txt) 
print(txt) 

Zuerst ist Ihre Druckanweisung in der Schleife, daher die doppelten Strings.

Zweitens Ihre re.sub (...) wird, um die Änderungen zu 'txt' für jede Rückkehr passieren durch die Schlaufe. Wenn Sie möchten akkumulieren die Änderungen müssen Sie die Ergebnisse zurück zu 'txt' zuweisen. Andernfalls sehen Sie nur die letzte Substitution, die 'a' zugeordnet ist.

Drittens "" .join (Muster) Ergebnisse in einem String "thia Finte", die kein Teil der 'txt' wird übereinstimmen.

Ich hoffe, das hilft. Reguläre Ausdrücke sind Disziplin für sich. Ich benutze sie seit den 80er Jahren und muss immer noch die Docs überprüfen. Mach weiter!