2009-01-22 11 views
6

patrones de expresiones regulares de Python compilados have a findall method que hace lo siguiente:¿Hay un equivalente Perl de re.findall/re.finditer de Python (resultados de expresiones regulares iterativas)? En

Volver todos los partidos que no se solapan de patrón en cadena, como una lista de cadenas . La cadena se escanea de izquierda a derecha, y las coincidencias son devueltas en el orden encontrado. Si hay uno o más grupos en el patrón , devuelva una lista de grupos; este 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.

¿Cuál es la forma canónica de hacer esto en Perl? Un algoritmo ingenuo en el que puedo pensar es en la línea de "mientras una búsqueda y reemplazo con la cadena vacía es exitosa, haz [suite]". Espero que haya una manera más agradable. :-)

Gracias de antemano!

Respuesta

13

Usa el modificador /g en tu partida. Del manual perlop:

El "/g" modificador especifica concordancia con el modelo mundial - es decir, a juego tantas veces como sea posible dentro de la cadena. Cómo se comporta depende del contexto. En el contexto de la lista, devuelve una lista de las subcadenas que coinciden con cualquier paréntesis de captura en la expresión regular. Si no hay paréntesis, devuelve una lista de todas las cadenas coincidentes, como si hubiera paréntesis alrededor de todo el patrón.

En contexto escalar, cada ejecución de "m//g" encuentra la siguiente coincidencia, devuelve verdadero si coincide y falso si no hay más coincidencias. La posición después de la última coincidencia se puede leer o configurar usando la función pos(); vea "pos" en perlfunc. Una coincidencia fallida normalmente restablece la posición de búsqueda al principio de la cadena, pero puede evitar eso agregando el modificador "/c" (por ejemplo, "m//gc"). La modificación de la cadena objetivo también restablece la posición de búsqueda.

+0

D'oh - por supuesto! Debería haberme dado cuenta de esto viniendo de la tierra de Vim. – cdleary

7

Para construir sobre la respuesta de Chris, que es probablemente más relevante para encerrar la expresión regular //g en un bucle while, como:

my @matches; 
while ('foobarbaz' =~ m/([aeiou])/g) 
{ 
    push @matches, $1; 
} 

pegar algunos rápida Python E/S:

>>> import re 
>>> re.findall(r'([aeiou])([nrs])','I had a sandwich for lunch') 
[('a', 'n'), ('o', 'r'), ('u', 'n')] 

Para obtener algo similar en Perl, la construcción podría ser algo así como:

my $matches = []; 
while ('I had a sandwich for lunch' =~ m/([aeiou])([nrs])/g) 
{ 
    push @$matches, [$1,$2]; 
} 

Pero, en general, cualquiera sea la función que esté iterando, probablemente pueda hacerlo dentro del propio bucle while.

+1

Pero, ¿qué pasa con '@matches = 'Tuve un sándwich para el almuerzo' = ~ m/([aeiou]) ([nrs])/g'? Claro, obtienes una matriz aplanada, pero luego puedes dividirla en dos (en este caso). :-) –

+0

Ah-hm. ¡La belleza de Perl es que siempre hay otra manera! Me alegro de haber dicho, "podría ser algo así como" :) – kyle

Cuestiones relacionadas