2011-02-10 20 views
23

Dezorientuje mnie zwracanie wielu grup w Pythonie. Moja RegEx to:Python RegEx wielu grup

lun_q = 'Lun:\s*(\d+\s?)*' 

A mój ciąg jest

s = '''Lun:      0 1 2 3 295 296 297 298'''` 

wrócę dopasowanego obiektu, a następnie zajrzeć do grup, ale wszystko to pokazuje, że ostatni numer (258):

r.groups() 
(u'298',) 

Dlaczego nie powraca grupa 0,1,2,3,4 itp?

+3

myślę co bezpośrednio odnoszą się nazywa [Przechwytywanie powtarzającego Group] (http://www.regular-expressions.info/captureall .html) - lub wzdłuż linii "dostęp do każdego dopasowania w ilościowo/powtórzonej grupie przechwytywania". zobacz [tę podobną odpowiedź] (http://stackoverflow.com/a/3537914/611007) dla javascript. nie wiem na pewno, ale *** wydają się być nieobsługiwane w smaku Pythona ***. zobacz [związane z pytaniem o rozszerzenie pythona] (http://bugs.python.org/issue7132) i [powiązane pytanie] (http://stackoverflow.com/q/15908085/611007) – n611x007

Odpowiedz

20

Twój regex zawiera tylko jedną parę nawiasów (jedna grupa przechwytywania), więc dostajesz tylko jedną grupę w swoim meczu. Jeśli użyjesz operatora powtórzeń w grupie przechwytującej (+ lub *), grupa zostanie "nadpisana" przy każdym powtórzeniu grupy, co oznacza, że ​​przechwycony zostanie tylko ostatni mecz.

W przykładzie tutaj, jesteś prawdopodobnie lepiej wyłączyć za pomocą .split(), w połączeniu z regex:

lun_q = 'Lun:\s*(\d+(?:\s+\d+)*)' 
s = '''Lun: 0 1 2 3 295 296 297 298''' 

r = re.search(lun_q, s) 

if r: 
    luns = r.group(1).split() 

    # optionally, also convert luns from strings to integers 
    luns = [int(lun) for lun in luns] 
+3

Picking 're.match()' vs 're.split()' jest nietrywialną decyzją – smci

2

Innym podejściem byłoby użyć regex trzeba zweryfikować swoje dane, a następnie użyć bardziej konkretne wyrażenie regularne kierowane na każdy element, który chcesz wyodrębnić za pomocą iteratora dopasowania.

import re 
s = '''Lun: 0 1 2 3 295 296 297 298''' 
lun_validate_regex = re.compile(r'Lun:\s*((\d+)(\s\d+)*)') 
match = lun_validate_regex.match(s) 
if match: 
    token_regex = re.compile(r"\d{1,3}") 
    match_iterator = token_regex.finditer(match.group(1)) 
    for token_match in match_iterator: 
     #do something brilliant 
+0

print re.findall ('\ d', s) –

6

Czasami jest łatwiejsze bez wyrażeń regularnych.

>>> s = '''Lun: 0 1 2 3 295 296 297 298''' 
>>> if "Lun: " in s: 
...  items = s.replace("Lun: ","").split() 
...  for n in items: 
...  if n.isdigit(): 
...   print n 
... 
0 
1 
2 
3 
295 
296 
297 
298 
1

Jeśli szukasz wyjścia takie jak 0,1,2,3,4 itp simples odpowiedź jest poniżej.

druku re.findall ('\ d', s)