Python Regex - So erhalten Sie Positionen und Werte von Übereinstimmungen

110

Wie kann ich mit dem reModul die Start- und Endpositionen aller Spiele ermitteln ? Zum Beispiel möchte ich angesichts des Musters r'[a-z]'und der Zeichenfolge 'a1b2c3d4'die Positionen erhalten, an denen jeder Buchstabe gefunden wird. Im Idealfall möchte ich auch den Text des Spiels zurückbekommen.

Greg
quelle
Sehen Sie, ob dies hilft, Objekte
abzugleichen

Antworten:

139
import re
p = re.compile("[a-z]")
for m in p.finditer('a1b2c3d4'):
    print(m.start(), m.group())
Peter Hoffmann
quelle
3
Dies liefert keinen Index für andere Gruppen in einer Übereinstimmung. Regex = r '([az]) (0-9)' m.start gilt für Gruppe (), nicht für Gruppe (1)
StevenWernerCS
@StevenWernerCS start()akzeptiert möglicherweise eine Gruppennummer. Wenn Sie also einen Index der n-ten Gruppe wünschen, verwenden Siestart(n)
Hi-Angel
@ hi-angel yep, siehe meine Antwort vom letzten Jahr, die genau das tut
StevenWernerCS
51

Genommen von

Regulärer Ausdruck HOWTO

span () gibt sowohl Start- als auch Endindizes in einem einzigen Tupel zurück. Da die Übereinstimmungsmethode nur prüft, ob die RE am Anfang eines Strings übereinstimmt, ist start () immer Null. Die Suchmethode von RegexObject-Instanzen durchsucht jedoch die Zeichenfolge, sodass die Übereinstimmung in diesem Fall möglicherweise nicht bei Null beginnt.

>>> 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)

Kombinieren Sie das mit:

In Python 2.2 ist auch die finditer () -Methode verfügbar, die eine Folge von MatchObject-Instanzen als Iterator zurückgibt.

>>> 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)

Sie sollten in der Lage sein, etwas in der Größenordnung von zu tun

for match in re.finditer(r'[a-z]', 'a1b2c3d4'):
   print match.span()
Weg
quelle
Sie können es verwenden wie re.search(r'abbit', "has abbit of carrot").span(0)-(4, 9)
Константин Ван
Der 'Endindex', der von zurückgegeben wird, span()ist wie der 'Stopp' in Pythons Slice-Notation, da er bis zu diesem Index reicht, diesen jedoch nicht enthält. siehe hier .
Wayne
20

Für Python 3.x.

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

Sie erhalten \nfür jeden Treffer in der Zeichenfolge getrennte Tupel (bestehend aus dem ersten und dem letzten Index des Spiels) und das Spiel selbst.

Widder hier
quelle
2

Beachten Sie, dass der Bereich und die Gruppe für mehrere Erfassungsgruppen in einem regulären Ausdruck indiziert sind

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))
StevenWernerCS
quelle
1
Danke, das hat sich als super nützlich erwiesen und scheint ziemlich begraben zu sein. Falls jemand dies benötigt: Wenn Sie benannte Erfassungsgruppen verwenden, können Sie den Index einer Gruppe mit <match> .re.groupindex ermitteln und von dort aus die entsprechende Spanne mit dem von Ihnen beschriebenen Ansatz ermitteln
madimov
Woher kommt das 4?
Funkgesteuert
@RadioControlled number_of_known_groups_in_the_regex + 1, da der Bereich [Start, Ende] ohne Ende ist
StevenWernerCS
@StevenWernerCS so dass es zu Fällen nicht verallgemeinert nicht , wo Anzahl der Gruppen ist nicht bekannt ...
Radio Controlled