usar test solo regulares regular probar online numeros net expresiones examples example como regex perl compilation modifier

regex - test - ¿Cómo fuerza a Perl a volver a compilar una expresión regular compilada con "/ o" a pedido?



regex vb.net example (3)

Pregunta técnica:

Dada una expresión regular:

my $regEx = qr{whatever$myVar}oxi; # Notice /o for "compile-once"

¿Cuál es la forma más efectiva de obligarlo a recompilar a pedido ? (por ejemplo, cuando sé por la lógica del programa que el valor de $myVar cambió) sin soltar /o y dependiendo de la inteligencia interna de Perl para autocompilar?

NOTA: La expresión regular se utiliza en una sustitución, lo que puede afectar a las reglas de recompilación sans / o:

$string2 =~ s/$regEx//;

El contexto es:

  • Tengo una expresión regular que está construida por sorber en una cadena bastante larga (> 1k de longitud) desde un archivo de configuración.

    • Ese archivo se vuelve a leer una vez cada 60 minutos.

    • Si la cadena leída del archivo cambia (como se define al cambiar la marca de tiempo del archivo), quiero volver a compilar la expresión regular usando el valor de la cadena reutilizada en $myVar .

  • La expresión regular se utiliza de manera repetida y frecuente en el módulo Perl que se ejecuta bajo mod_perl.

    • Esto significa que (junto con la cadena que tiene> 1-2k de longitud) debo usar el modificador " /o " para forzar la compilación una vez en la expresión regular, para evitar el golpe de rendimiento de Perl comprobando repetidamente si el valor de la variable cambió (esta heurística es de perlop qr// , ya que la expresión regular se usa como parte de s/// como se muestra arriba y no solo como una coincidencia).

    • Eso a su vez significa que, cuando sé que la variable cambió después de volver a sorberlo en 1 hora, necesito forzar a la expresión regular a volver a compilar a pesar del modificador /o .

ACTUALIZACIÓN: Aquí hay una ilustración de por qué necesito /o - sin ella, la expresión regular se recompila (y, por lo tanto, se comprueba necesariamente) cada iteración de ciclo; con eso NO es:

$ perl -e ''{for (my $i=0; $i<3; $i++) { my $re = qr{$i}oix; $s="123"; $s =~ s/$re//; print "i=$i; s=$s/n"; }}'' i=0; s=123 i=1; s=123 i=2; s=123 $ perl -e ''{ for (my $i=0; $i<3; $i++) { my $re = qr{$i}ix; $s="123"; $s =~ s/$re//; print "i=$i; s=$s/n"; }}'' i=0; s=123 i=1; s=23 i=2; s=13


cuando sé por la lógica del programa que el valor de $ myVar cambió

m// , s/// y qr// solo compilan si el patrón no cambia. Todo lo que tiene que hacer para obtener el comportamiento que solicitó es eliminar el /o .

$ perl -Mre=debug -e'' qr/$_/ for qw( abc abc def def abc abc ); '' 2>&1 | grep Compiling Compiling REx "abc" Compiling REx "def" Compiling REx "abc"

Por lo tanto,

Si la cadena leída del archivo cambia (como se define al cambiar la marca de tiempo del archivo), quiero volver a compilar la expresión regular usando el valor de la cadena reutilizada en $ myVar.

my $new_myVar = ...; if ($myVar ne $new_myVar) { $re = qr/$new_myVar/; $myVar = $new_myVar; } ... s/$re/.../

o solo

$myVar = ...; ... s/$myVar/.../


Básicamente respondiste tu propia pregunta. Use qr{...} para crear un objeto regexp compilado y luego úselo:

my $re = qr{...}; ... if ($str =~ $re) { # this used the statically compiled object } ... if ($time_to_recompile) { $re = qr{...}; }

Ni siquiera necesitas el modificador "/ o".


De acuerdo con perlop

El efecto que tiene el modificador ''o'' no se propaga, estando restringido a aquellos patrones que lo usan explícitamente.

Entonces, si escribes

my $str = ''x''; my $re = qr/$str/o; ... if (s/$re//) { ... }

Perl aún comprobará si $re ha cambiado o no al ejecutar el s/// . El /o actúa como una promesa de que el valor de $str utilizado en la compilación de $re no cambiará, por lo que si volviera a ejecutar el qr// obtendrá el mismo resultado incluso si $str ha cambiado. Puedes ver esto en efecto con el use re ''debug'' :

use strict; use warnings; use re ''debug''; foreach my $i (0 .. 2) { my $s = ''123''; print STDERR "Setting /$re/n"; my $re = qr/$i/o; print STDERR "Performing s////n"; $s =~ s/$re//; }

Con el modificador /o , solo verá "Compilar REx ..." después de "Configurar $ re" la primera vez a través del ciclo. Sin él, lo verás en cada iteración.

El take-away es que si quieres cambiar el patrón durante el tiempo de ejecución no deberías usar /o . No afectará el s/// y evitará que pueda volver a compilar $re cuando lo necesite.