2016-09-19 4 views
1

Ich suchte nach einer effizienten Möglichkeit, einen Teilstring zwischen zwei Ausdrücken zu finden, es sei denn, der Ausdruck ist Teil eines anderen.Finden Sie einen Teilstring im Textblock, es sei denn, es ist Teil eines anderen Teilstrings

Zum Beispiel:

Es ist einmal, in einer Zeit, weit weit weg, herrschten Hunde der Welt. Das Ende.

Wenn ich für die Teilkette zwischen Zeit und Ende war auf der Suche, würde ich erhalten:

in einer Zeit weit weit weg, herrschten Hunde der Welt. Die

oder

weit weit weg, herrschten Hunde der Welt. Die

Ich möchte ignorieren, wenn Zeit ein Teil war einmal ist. Ich wusste nicht, ob es eine pythonische Methode gab, ohne verrückte for-Schleifen und if/else-Fälle zu verwenden.

+1

Was Sie bisher getan haben? –

+1

Können Sie die gewünschte Ausgabe klären? Sie möchten das maximale (gierige) Match oder das minimale Match? – wim

+0

Ich möchte 'weit weit weg, Hunde regiert die Welt. Das '(minimal) @wim – Michael

Antwort

1

Entfernen Sie einfach "Es war einmal" und überprüfen Sie, was übrig ist.

my_string = 'Once upon a time, in a time far far away, dogs ruled the world. The End.' 
if 'time' in my_string.replace('Once upon a time', ''): 
    pass 
+0

Okay, das würde in meinem Fall funktionieren .. danke! – Michael

0

Die typische Lösung hier ist die Verwendung von regulären und regulären Gruppen für die Erfassung von Captures. Da Regex-Änderungen von links nach rechts geparst werden, setzen Sie zuerst Ausnahmen auf die Regel (als Nicht-Capture) und enden mit dem Wechsel, für den Sie auswählen möchten.

import re 

text = "Once upon a time, in a time far far away, dogs ruled the world. The End." 
query = re.compile(r""" 
    Once upon a time|   # literally 'Once upon a time', 
           # should not be selected 
    time\b      # from the word 'time' 
    (.*)       # capture everything 
    \bend      # until the word 'end' 
""", re.X | re.I) 

result = query.findall(text) 
# result = ['', ' far far away, dogs ruled the world. The '] 

Sie können die leere Gruppe Streifen aus (die in gesetzt wurde, wenn wir die unerwünschte Zeichenfolge angepasst)

result = list(filter(None, result)) 
# or result = [r for r in result if r] 
# [' far far away, dogs ruled the world. The '] 

und dann die Ergebnisse Streifen

result = list(map(str.strip, filter(None, result))) 
# or result = [r.strip() for r in result if r] 
# ['far far away, dogs ruled the world. The'] 

Diese Lösung ist besonders nützlich, Wenn Sie eine Reihe von Phrasen haben, denen Sie ausweichen möchten.

phrases = ["Once upon a time", "No time like the present", "Time to die", "All we have left is time"] 
querystring = r"time\b(.*)\bend" 
query = re.compile("|".join(map(re.escape, phrases)) + "|" + querystring, re.I) 

result = [r.strip() for r in query.findall(some_text) if r] 
2

Dies ist möglich, in regex durch einen negativen Look-Ahead mit

>>> s = 'Once upon a time, in a time far far away, dogs ruled the world. The End.' 
>>> pattern = r'time((?:(?!time).)*)End' 
>>> re.findall(pattern, s) 
[' far far away, dogs ruled the world. The '] 

Mit mehreren Begegnungen:

>>> s = 'a time b End time c time d End time' 
>>> re.findall(pattern, s) 
[' b ', ' d '] 
+0

Versuchen wir, die innerste "Zeit ... Ende" zu finden oder einfach die Phrase "Es war einmal" zu vermeiden? Die Frage implizierte Letzteres, aber ich bin mir nicht sicher. –

+1

Nicht sicher. Ich dachte, der erste schien ein praktischerer Anwendungsfall zu sein.Ich schätze, wir lassen beide Antworten für zukünftige Leser hier ... – wim

Verwandte Themen