2012-12-25 7 views
6

Wenn ich versuche, reguläre Ausdrücke zu verwenden, um Zeichenfolgen in anderen Zeichenfolgen zu finden, funktioniert es nicht wie erwartet. Hier ein Beispiel:Suchzeichenfolgen mit regulärem Ausdruck in Python

import re 
message = 'I really like beer, but my favourite beer is German beer.' 
keywords = ['beer', 'german beer', 'german'] 

regex = re.compile("|".join(keywords)) 
regex.findall(message.lower()) 

Ergebnis:

['beer', 'beer', 'german beer'] 

Aber das erwartete Ergebnis wäre:

['beer', 'beer', 'german beer', 'german'] 

Eine andere Möglichkeit, das zu tun sein könnte:

results = [] 
for k in keywords: 
    regex = re.compile(k) 
    for r in regex.findall(message.lower()): 
     results.append(r) 

['beer', 'beer', 'beer', 'german beer', 'german'] 

Es funktioniert wie ich will, aber ich denke es ist n Das ist der beste Weg, das zu tun. Kann mir jemand helfen?

Antwort

6

re.findall können überlappende Übereinstimmungen nicht gefunden werden. Wenn Sie reguläre Ausdrücke verwenden möchten, müssen Sie separate Ausdrücke erstellen und sie wie in Ihrem zweiten Beispiel in einer Schleife ausführen.

Beachten Sie, dass Ihr zweites Beispiel kann auch auf die folgenden verkürzt werden, wenn es eine Frage des Geschmacks ist, ob Sie diese besser lesbar finden:

results = [r for k in keywords for r in re.findall(k, message.lower())] 

Ihr spezifisches Beispiel nicht die Verwendung von regulären Ausdrücken erfordern. Sie sollten die Verwendung von regulären Ausdrücken vermeiden, wenn Sie nur feste Zeichenfolgen suchen möchten.

+0

Der Fragesteller nicht nur testen wollen, ob ein bestimmter Teilkette einen Teil eines Strings ist, aber er will alle Vorkommen eines bestimmten Teilkette. In diesem Fall ist die Verwendung von 're.findall()' der beste Weg, dies zu erreichen. Das Vermeiden von regulären Ausdrücken würde diese Lösung mühsamer als notwendig machen. – pemistahl

+0

Danke euch für eure Antworten. Jetzt weiß ich, dass ich eine falsche Funktion verwende (findall), also was empfehlen Sie für Übereinstimmungen, einschließlich Überlappungen? –

+0

@ Adrián: Brauchst du die Macht von regulären Ausdrücken oder willst du nur feste Strings finden? –

6

re.findall beschrieben in http://docs.python.org/2/library/re.html

„Gibt alle nicht-überlappende Spiele von Muster in String ...“

Nicht überlappende bedeutet, dass für „Deutsch Bier“ wird es nicht „Deutsch Bier“ finden UND "Deutsch", weil diese Übereinstimmungen sich überschneiden.

+0

Danke für Ihre Antwort Omri Barel. Was empfehlen Sie für das Finden von Übereinstimmungen, einschließlich Überlappungen? –

+0

Im Allgemeinen müssen Sie tun, was Sie getan haben: ein Schlüsselwort nach dem anderen. Aber für eine bessere Lösung müssen Sie beschreiben, was Sie wirklich versuchen (d. H. Was ist die tatsächliche Situation, ohne zu trivialen Beispielen zu vereinfachen). –

+0

Omri, wie ich in der Antwort unten schreibe, fragte ich nach regulären Ausdrücken, weil ich dachte, dass es der beste und optimale Weg ist, dies zu tun. Die Strings für find werden immer fest sein (word1 | word2 | word3 ...), ich meine keine komplexe Regex. –

1

Mein Reiniger (für mich) Version für Ihre letzte Lösung

results = [] 
for key in keywords: 
    results.extend(re.findall(key, message, re.IGNORECASE)) 
Verwandte Themen