¿El modificador ‘o’ para las expresiones regulares de Perl aún proporciona algún beneficio?

Solía ​​considerarse beneficioso incluir el modificador ‘o’ al final de las expresiones regulares de Perl. La documentación actual de Perl ni siquiera parece enumerarla, ciertamente no en la sección de modificadores de perlre .

¿Proporciona algún beneficio ahora?

Todavía se acepta, por razones de compatibilidad con versiones anteriores, nada más.


Como lo señalan JA Faucett y Brian Foy, el modificador ‘o’ aún está documentado, si encuentra los lugares correctos para mirar (uno de los cuales no es la documentación perlre ). Se menciona en las páginas de perlop . También se encuentra en las páginas perlreref .

Como señaló Alan M en la respuesta aceptada, la mejor técnica moderna suele ser utilizar el operador qr // (regex citado).

Estoy seguro de que todavía es compatible, pero es bastante obsoleto. Si desea que la expresión regular se compile solo una vez, es mejor que utilice un objeto regex, así:

 my $reg = qr/foo$bar/; 

La interpolación de $bar se realiza cuando la variable se inicializa, por lo que siempre usará la expresión regular comstackda en caché a partir de ese momento dentro del scope adjunto. Pero a veces quiere que se recompile la expresión regular, porque quiere que use el nuevo valor de la variable. Este es el ejemplo que Friedl usó en The Book :

 sub CheckLogfileForToday() { my $today = (qw)[(localtime)[6]]; my $today_regex = qr/^$today:/i; # compiles once per function call while () { if ($_ =~ $today_regex) { ... } } } 

Dentro del scope de la función, el valor de $ today_regex se mantiene igual. Pero la próxima vez que se llame a la función, la expresión regular se volverá a comstackr con el nuevo valor de $today . Si él acabara de usar

 if ($_ =~ m/^$today:/io) 

… la expresión regular nunca se actualizará. Entonces, con la forma de objeto, tiene la eficiencia de / o sin sacrificar la flexibilidad.

El modificador /o está en la documentación de perlop en lugar de la documentación de perlre , ya que es un modificador de tipo cita en lugar de un modificador de expresiones regulares. Eso siempre me ha parecido extraño, pero así son las cosas. Desde Perl 5.20, ahora está listado en perlre simplemente para notar que probablemente no deberías usarlo.

Antes de Perl 5.6, Perl recomstackba la expresión regular incluso si la variable no había cambiado. No necesitas hacer eso nunca más. Puede usar /o para comstackr la expresión regular una vez a pesar de los cambios adicionales a la variable, pero como se señaló en las otras respuestas, qr// es mejor para eso.

En la documentación de Perl 5 versión 20.0 http://perldoc.perl.org/perlre.html declara

 Modifiers Other Modifiers … o - pretend to optimize your code, but actually introduce bugs 

que puede ser una forma graciosa de decir que se suponía que debía realizar algún tipo de optimización, pero la implementación no funciona.

Por lo tanto, la mejor opción es evitarla.

Esta es una optimización en el caso de que la expresión regular incluya una referencia de variable. Indica que la expresión regular no cambia aunque tenga una variable dentro. Esto permite optimizaciones que de otro modo no serían posibles.

Aquí hay horarios para diferentes formas de llamar a la coincidencia.

 $ perl -v | grep version This is perl 5, version 20, subversion 1 (v5.20.1) built for x86_64-linux-gnu-thread-multi $ perl const-in-re-once.pl | sort 0.200 =~ CONST 0.200 =~ m/$VAR/o 0.204 =~ m/literal-wo-vars/ 0.252 =~ m,@{[ CONST ]},o 0.260 =~ $VAR 0.276 =~ m/$VAR/ 0.336 =~ m,@{[ CONST ]}, 

Mi código:

 #! /usr/bin/env perl use strict; use warnings; use Time::HiRes qw/ tv_interval clock_gettime gettimeofday /; use BSD::Resource qw/ getrusage RUSAGE_SELF /; use constant RE => qr{ https?:// (?:[^.]+-d-[^.]+\.)? (?:(?: (?:dev-)? nind[^.]* | mr02 )\.)? (?:(?:pda|m)\.)? (?:(?:news|haber)\.) (?:.+\.)? yandex\. .+ }x; use constant FINAL_RE => qr,^@{[ RE ]}(/|$),; my $RE = RE; use constant ITER_COUNT => 1e5; use constant URL => 'http://news.trofimenkov.nerpa.yandex.ru/yandsearch?cl4url=www.forbes.ru%2Fnews%2F276745-visa-otklyuchila-rossiiskie-banki-v-krymu&lr=213&lang=ru'; timeit( '=~ m/literal-wo-vars/', ITER_COUNT, sub { for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ m{ ^https?:// (?:[^.]+-d-[^.]+\.)? (?:(?: (?:dev-)? nind[^.]* | mr02 )\.)? (?:(?:pda|m)\.)? (?:(?:news|haber)\.) (?:.+\.)? yandex\. .+ (/|$) }x } } ); timeit( '=~ m/$VAR/', ITER_COUNT, sub { for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ m,^$RE(/|$), } } ); timeit( '=~ $VAR', ITER_COUNT, sub { my $r = qr,^$RE(/|$),o; for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ $r } } ); timeit( '=~ m/$VAR/o', ITER_COUNT, sub { for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ m,^$RE(/|$),o } } ); timeit( '=~ m,@{[ CONST ]},', ITER_COUNT, sub { for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ m,^@{[ RE ]}(/|$), } } ); timeit( '=~ m,@{[ CONST ]},o', ITER_COUNT, sub { for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ m,^@{[ RE ]}(/|$),o } } ); timeit( '=~ CONST', ITER_COUNT, sub { my $r = qr,^$RE(/|$),o; for (my $i = 0; $i < ITER_COUNT; ++$i) { URL =~ FINAL_RE } } ); sub timeit { my ($name, $iters, $code) = @_; #my $t0 = [gettimeofday]; my $t0 = (getrusage RUSAGE_SELF)[0]; $code->(); #my $el = tv_interval($t0); my $el = (getrusage RUSAGE_SELF)[0] - $t0; printf "%.3f\t%-17s\t%.9f\n", $el, $name, $el / $iters } 

Una cosa que, desconcertantemente, no es, permite un locking de ONCE, al menos en 5.8.8.

perl -le 'for (1..3){ print; m/${\(print( "between 1 and 2 only"), 3)}/o and print "matched" }'