Python Regex - jak uzyskać pozycje i wartości dopasowań


112

Jak mogę uzyskać pozycje początkową i końcową wszystkich meczów za pomocą remodułu? Na przykład biorąc pod uwagę wzór r'[a-z]'i ciąg znaków 'a1b2c3d4', chciałbym uzyskać pozycje, w których znajduje każdą literę. Idealnie, chciałbym również odzyskać tekst dopasowania.


Sprawdź, czy to pomoże dopasować obiekty
EBGreen

Odpowiedzi:


140
import re
p = re.compile("[a-z]")
for m in p.finditer('a1b2c3d4'):
    print(m.start(), m.group())

3
To nie zapewnia indeksu innych grup w dopasowaniu regex = r '([az]) (0-9)' m.start będzie dla grupy (), a nie grupy (1)
StevenWernerCS

@StevenWernerCS start()może akceptować numer grupy, więc jeśli chcesz mieć indeks n-tej grupy, użyjstart(n)
Hi-Angel

@ hi-angel yep, zobacz poniżej moją odpowiedź z zeszłego roku, która właśnie to robi
StevenWernerCS

51

Pochodzą z

Wyrażenia regularne HOWTO

span () zwraca indeksy początkowy i końcowy w jednej krotce. Ponieważ metoda match sprawdza tylko, czy RE pasuje na początku łańcucha, start () zawsze będzie równy zero. Jednak metoda wyszukiwania wystąpień RegexObject skanuje ciąg, więc dopasowanie może w takim przypadku nie rozpoczynać się od zera.

>>> p = re.compile('[a-z]+')
>>> print p.match('::: message')
None
>>> m = p.search('::: message') ; print m
<re.MatchObject instance at 80c9650>
>>> m.group()
'message'
>>> m.span()
(4, 11)

Połącz to z:

W Pythonie 2.2 dostępna jest również metoda finditer (), zwracająca sekwencję instancji MatchObject jako iterator.

>>> p = re.compile( ... )
>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> iterator
<callable-iterator object at 0x401833ac>
>>> for match in iterator:
...     print match.span()
...
(0, 2)
(22, 24)
(29, 31)

powinieneś być w stanie zrobić coś na zlecenie

for match in re.finditer(r'[a-z]', 'a1b2c3d4'):
   print match.span()

Możesz go używać tak, jak re.search(r'abbit', "has abbit of carrot").span(0)-(4, 9)
Константин Ван

„End index” zwrócony przez the span()jest podobny do „stop” w notacji wycinka Pythona pod tym względem, że idzie do góry, ale nie zawiera tego indeksu; zobacz tutaj .
Wayne

20

W przypadku Pythona 3.x

from re import finditer
for match in finditer("pattern", "string"):
    print(match.span(), match.group())

Otrzymasz \noddzielne krotki (zawierające odpowiednio pierwszy i ostatni indeks dopasowania) oraz samo dopasowanie dla każdego trafienia w ciągu.


2

zwróć uwagę, że zakres i grupa są indeksowane w przypadku wielu grup przechwytywania w wyrażeniu regularnym

regex_with_3_groups=r"([a-z])([0-9]+)([A-Z])"
for match in re.finditer(regex_with_3_groups, string):
    for idx in range(0, 4):
        print(match.span(idx), match.group(idx))

1
Dzięki, okazało się to bardzo przydatne i wydaje się być całkiem zakopane. Również na wypadek, gdyby ktoś tego potrzebował: używając nazwanych grup przechwytywania, można znaleźć indeks grupy za pomocą <match> .re.groupindex, a stamtąd znaleźć odpowiedni zakres, używając podejścia, które przedstawiłeś
madimov

skąd się 4bierze?
Kontrolowane radiowo

@RadioControlled number_of_known_groups_in_the_regex + 1, ponieważ zakres to [początek, koniec) bez końca
StevenWernerCS

@StevenWernerCS, więc nie uogólnia się przypadków, w których liczba grup nie jest znana ...
Sterowanie radiowe
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.