2011-02-10 30 views
23

Me estoy confundiendo al devolver varios grupos en Python. Mi RegEx es la siguiente:Python RegEx grupos múltiples

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

Y mi cadena es

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

vuelvo un objeto emparejado, y luego quiero mirar a los grupos, pero todo lo que muestra que el último número (258):

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

¿Por qué no se lo va a devolver grupos de 0,1,2,3,4 etc.?

+3

Creo que lo que se refieren directamente al que se llama [Captura de un grupo repetido] (http://www.regular-expressions.info/captureall .html) - o a lo largo de las líneas 'acceder a cada coincidencia en un grupo de captura cuantificado/repetido'. ver [esta respuesta similar] (http://stackoverflow.com/a/3537914/611007) para javascript. no estoy seguro pero *** parecen no estar respaldados en el sabor de la expresión regular de Python ***. ver [solicitud de mejora de Python relacionada] (http://bugs.python.org/issue7132) y [pregunta relacionada] (http://stackoverflow.com/q/15908085/611007) – n611x007

Respuesta

20

Su expresión regular solo contiene un par de paréntesis (un grupo de captura), por lo que solo obtendrá un grupo en su coincidencia. Si utiliza un operador de repetición en un grupo de captura (+ o *), el grupo se "sobrescribe" cada vez que se repite el grupo, lo que significa que solo se captura la última coincidencia.

En el ejemplo aquí, usted es probablemente mejor usar .split(), en combinación con una expresión regular:

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

Escoger 're.match()' contra 're.split()' es una decisión no trivial – smci

2

Otro enfoque sería utilizar la expresión regular que tiene que validar sus datos y luego utilizar una mayor expresión regular específica que se dirige a cada elemento que desea extraer utilizando un iterador de coincidencia.

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

A veces, es más fácil sin expresiones regulares.

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

Si está buscando una salida tales como 0,1,2,3,4 etc La respuesta simples está por debajo.

de impresión re.findall ('\ d', s)

Cuestiones relacionadas