Wie finde ich überlappende Übereinstimmungen mit einem regulären Ausdruck?


76
>>> match = re.findall(r'\w\w', 'hello')
>>> print match
['he', 'll']

Da \ w \ w zwei Zeichen bedeutet, werden 'er' und 'll' erwartet. Aber warum passen 'el' und 'lo' nicht zum regulären Ausdruck?

>>> match1 = re.findall(r'el', 'hello')
>>> print match1
['el']
>>>

Antworten:


106

findallliefert standardmäßig keine überlappenden Übereinstimmungen. Dieser Ausdruck tut jedoch:

>>> re.findall(r'(?=(\w\w))', 'hello')
['he', 'el', 'll', 'lo']

Hier (?=...)ist eine Lookahead-Behauptung :

(?=...)stimmt ...überein, wenn der nächste übereinstimmt, verbraucht aber keinen der Zeichenfolgen. Dies wird als Lookahead-Behauptung bezeichnet. Zum Beispiel Isaac (?=Asimov)wird 'Isaac 'nur übereinstimmen , wenn es gefolgt wird 'Asimov'.


Aber ich verstehe nicht, warum es zum nächsten Buchstaben übergeht, wenn es in der positiven Lookahead-Behauptung liegt. Könnten Sie das bitte erklären?
MrZH6

39

Sie können das neue Python-Regex-Modul verwenden , das überlappende Übereinstimmungen unterstützt.

>>> import regex as re
>>> match = re.findall(r'\w\w', 'hello', overlapped=True)
>>> print match
['he', 'el', 'll', 'lo']

11

Mit Ausnahme der Zusicherung der Länge Null wird das Zeichen in der Eingabe beim Abgleich immer verbraucht. Wenn Sie jemals in dem Fall sind, dass Sie ein bestimmtes Zeichen in der Eingabezeichenfolge mehr als einmal erfassen möchten, benötigen Sie eine Bestätigung der Länge Null im regulären Ausdruck.

Es gibt mehrere Zusicherungen mit einer Länge von Null (z. B. ^(Beginn der Eingabe / Zeile), $(Ende der Eingabe / Zeile), \b(Wortgrenze)), aber nur Umschauen ( (?<=)positiver Blick nach hinten und (?=)positiver Blick nach vorne) sind möglich dass Sie überlappenden Text von der Eingabe erfassen können. Negative Look-arounds ( (?<!)negativer Look-Behind, (?!)negativer Look-Ahead) sind hier nicht sehr nützlich: Wenn sie wahr sind, ist die Erfassung im Inneren fehlgeschlagen. Wenn sie false bestätigen, schlägt die Übereinstimmung fehl. Diese Zusicherungen haben eine Länge von Null (wie bereits erwähnt), was bedeutet, dass sie ohne Verbrauch der Zeichen in der Eingabezeichenfolge bestätigt werden. Sie stimmen tatsächlich mit der leeren Zeichenfolge überein, wenn die Zusicherung erfolgreich ist.

Wenn Sie das oben genannte Wissen anwenden, wäre ein regulärer Ausdruck, der für Ihren Fall funktioniert, Folgendes:

(?=(\w\w))

0

Ich bin kein Regex-Experte, möchte aber meine ähnliche Frage beantworten .

Wenn Sie eine Erfassungsgruppe mit dem Lookahead verwenden möchten:

Beispiel Regex: (\ d) (? =. \ 1)

Zeichenfolge: 5252

Dies entspricht sowohl den ersten 5 als auch den ersten 2

Das (\ d) soll eine Erfassungsgruppe bilden, (? = \ D \ 1) soll mit jeder Ziffer übereinstimmen, gefolgt von der Erfassungsgruppe 1, ohne die Zeichenfolge zu verbrauchen, wodurch Überlappungen zugelassen werden

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.