2012-07-11 16 views
42
>>> match = re.findall(r'\w\w', 'hello') 
>>> print match 
['he', 'll'] 

Ponieważ \ w \ w oznacza dwa znaki, oczekuje się, że "on" i "ll". Ale dlaczego "el" i "lo" nie pasuje do wyrażenia regularnego?Jak znaleźć nakładające się mecze z wyrażeniem regularnym?

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

[Lookahead] (http://stackoverflow.com/questions/320448/overlapping-matches-in-regex) –

Odpowiedz

70

findall domyślnie nie przynosi nakładających się dopasowań. Wyrażenie to ma jednak:

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

Tutaj (?=...) jest lookahead assertion:

(?=...) Pasuje ... meczów najbliższych, ale nie zużywa dowolnego napisu . Nazywa się to twierdzeniem z wyprzedzeniem. Na przykład Isaac (?=Asimov) będzie pasować do 'Isaac ' tylko wtedy, gdy po nim nastąpi 'Asimov'.

7

Z wyjątkiem asercji o zerowej długości, znak na wejściu zawsze będzie używany w dopasowaniu. Jeśli kiedykolwiek będziesz chciał uchwycić pewną postać w ciągu wejściowym więcej razy, będziesz potrzebować asercji o zerowej długości w regex.

Istnieje kilka zerowej długości twierdzenie (np ^ (początek/wejście liniowe), $ (koniec/wejście liniowe), \b (granica słowo)), ale przeglądowej arounds ((?<=) pozytywny look-tył i (?=) pozytywne patrzenie w przyszłość) to jedyny sposób, w jaki można uchwycić nakładający się tekst z danych wejściowych. Negatywne rozglądanie się ((?<!) negatywne spojrzenie za, (?!) negatywne spojrzenie z wyprzedzeniem) nie są tu zbyt użyteczne: jeśli potwierdzą prawdziwość, przechwycenie w środku zakończyło się niepowodzeniem; jeśli potwierdzą fałsz, wówczas mecz się nie powiedzie. Twierdzenia te mają zerową długość (jak wspomniano wcześniej), co oznacza, że ​​będą twierdzić, nie pochłaniając znaków w łańcuchu wejściowym. W rzeczywistości będą pasować do pustego ciągu, jeśli twierdzenie przeminie.

Stosując powyższy wiedzy regex, który działa w Twoim przypadku będzie:

(?=(\w\w)) 
20

Można użyć new Python regex module, które obsługuje nakładające się mecze.

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