2011-08-14 27 views
6

¿Existe una manera conveniente de escribir una expresión regular que intente hacer coincidir la mayor cantidad de regex como sea posible?¿Tiene una expresión regular que coincida tanto como sea posible?

Ejemplo:

my $re = qr/a ([a-z]+) (\d+)/; 

match_longest($re, "a") =>() 
match_longest($re, "a word") => ("word") 
match_longest($re, "a word 123") => ("word", "123") 
match_longest($re, "a 123") =>() 

Es decir, $re se considera que es una secuencia de expresiones regulares, y match_longest intentos para que coincida con la mayor cantidad de esta secuencia. En cierto sentido, la coincidencia nunca falla, solo se trata de la cantidad de coincidencia exitosa. Una vez que falla una coincidencia de expresión regular, undef para las piezas que no coinciden.

Sé que podría escribir una función que toma una secuencia de expresiones regulares y crea una sola expresión regular para hacer el trabajo de match_longest. Aquí hay un resumen de la idea:

Supongamos que tiene tres expresiones regulares: $r1, $r2 y $r3. La única expresión regular para realizar el trabajo de match_longest tendría la siguiente estructura:

$r = ($r1 $r2 $r3)? | $r1 ($r2 $r3) | $r1 $r2 $r3? 

Por desgracia, esto es cuadrática en el número de expresiones regulares. ¿Es posible ser más eficiente?

+0

cambió el ejemplo de expresiones regulares desde '' 123' partidos \ w + ' – ErikR

Respuesta

5

Puede utilizar la expresión regular

$r = ($r1 ($r2 ($r3)?)?)? 

que tiene cada expresión regular contenía sólo una vez. También puede usar grupos que no sean de captura (?:...) en este ejemplo para no interferir con sus expresiones regulares originales.

+0

Esto solo capturará correctamente las partes cuando haya un espacio final presente. –

2

Si entiendo la pregunta, utilizando grupos anidados con ? debería funcionar:

my $re = qr/a ((\w+) (\d+)?)?/; 
+0

Esta expresión regular no coincide completamente con 'una palabra'. –

0

Este caso particular se puede escribir así:

m/a (?:(\w+)(?: (\d+))?)?/ 
Cuestiones relacionadas