2011-05-27 15 views
5

que redactó esta expresión regular:¿Por qué re.findall() me da resultados diferentes que re.finditer() en Python?

p = re.compile(r''' 
\[\[   #the first [[ 
[^:]*?   #no :s are allowed 
.*?    #a bunch of chars 
(
\|    #either go until a | 
|\]\]   #or the last ]] 
) 
       ''', re.VERBOSE) 

quiero usar re.findall para obtener todas las secciones coincidentes de un trozo de cuerda. Escribí un código de prueba, pero me da resultados extraños.

Este código

g = p.finditer(' [[Imae|Lol]]  [[sdfef]]') 
print g 
for elem in g: 
    print elem.span() 
    print elem.group() 

me da este resultado:

(3, 10) 
[[Imae| 
(20, 29) 
[[sdfef]] 

tiene mucho sentido ¿verdad? Pero cuando hago esto:

h = p.findall(' [[Imae|Lol]]  [[sdfef]]') 
for elem in h: 
    print elem 

la salida es la siguiente:

| 
]] 

¿Por qué no se FindAll() imprimir los mismos resultados que finditer ??

Respuesta

7

Findall devuelve una lista de grupos coincidentes. La parántesis en tu expresión regular define un grupo que finalmente cree que quieres, pero no quieres grupos. (?:...) es una paranthesis que no captura. Cambiar su expresión regular para:

''' 
\[\[   #the first [[ 
[^:]*?   #no :s are allowed 
.*?    #a bunch of chars 
(?:    #non-capturing group 
\|    #either go until a | 
|\]\]   #or the last ]] 
) 
       ''' 
+0

Esto resolvió el problema! Me olvidé un poco sobre Findall ... ¡gracias! –

1

creo que el paletón de la findall() documentation es la siguiente:

Si uno o más grupos están presentes en el patrón, devuelve una lista de grupos; esta será una lista de tuplas si el patrón tiene más de un grupo.

Su expresión regular tiene un grupo alrededor de la tubería o cerrar]] aquí:

(
\|    #either go until a | 
|\]\]   #or the last ]] 
) 

finditer() no parece tener ningún dicha cláusula.

+0

Útil. Gracias. :) –

1

No devuelven lo mismo. Algunos fragmentos de la docs:

findall devuelve una lista de cadenas. Si uno o más grupos están presentes en el patrón, devuelve una lista de grupos; esto será una lista de tuplas si el patrón tiene más de un grupo.

finditer devuelve un iterador produciendo instancias de MatchObject.

0

A partir de la documentación de Python:

Volver todos los partidos que no se solapan de patrón en la secuencia, como una lista de cadenas. La cadena se escanea de izquierda a derecha y las coincidencias se devuelven en el orden en que se encuentran. Si uno o más grupos están presentes en el patrón, devuelve una lista de grupos; esta será una lista de tuplas si el patrón tiene más de un grupo. Las coincidencias vacías se incluyen en el resultado a menos que toquen el comienzo de otra coincidencia.

Tenga en cuenta que dice que si hay grupos presentes, se devolverá una lista de las coincidencias de grupo. El grupo de captura que tiene al final de su expresión regular coincide y, por lo tanto, solo se devuelve la parte capturada de los grupos en cada coincidencia. Esta información es simplemente otro campo en el objeto MatchObject cuando usa finditer.

3

Cuando le da a re.findall() una expresión regular con grupos (expresiones entre paréntesis), devuelve grupos que coincidan. Aquí, solo tienes un grupo, y es el | o]] al final. Por otro lado, en el código donde usas re.finditer(), no estás pidiendo ningún grupo en particular, por lo que te da la cadena completa.

Puede obtener re.findall() para hacer lo que quiera poniendo paréntesis alrededor de la expresión regular completa, o simplemente alrededor de la parte que realmente está tratando de extraer. Suponiendo que estamos tratando de analizar los vínculos de Wikipedia, que sería el "grupo de caracteres" en la línea 4. Por ejemplo,

p = re.compile(r''' 
\[\[   #the first [[ 
[^:]*?   #no :s are allowed 
(.*?)   #a bunch of chars 
(
\|    #either go until a | 
|\]\]   #or the last ]] 
) 
       ''', re.VERBOSE) 

p.findall(' [[Imae|Lol]]  [[sdfef]]') 

devuelve:

[('Imae', '|'), ('sdfef', ']]')] 
+0

Whoa. Todo tiene sentido ahora. Es un buen trabajo descubrir lo que estaba buscando. –

Cuestiones relacionadas