Le modificateur ‘o’ pour les expressions régulières Perl offre-t-il toujours des avantages?

Autrefois, il était avantageux d’inclure le modificateur ‘o’ à la fin des expressions régulières Perl. La documentation actuelle de Perl ne semble même pas la lister, certainement pas dans la section des modificateurs de perlre .

Fournit-il des avantages maintenant?

Il est toujours accepté, pour des raisons de rétrocompatibilité, sinon rien.


Comme noté par JA Faucett et Brian D foy, le modificateur ‘o’ est toujours documenté, si vous trouvez les bons endroits à regarder (dont l’un n’est pas la documentation de perlre ). Il est mentionné dans les pages du perlop . Il se trouve également dans les pages de perlreref .

Comme l’a noté Alan M dans la réponse acceptée, la meilleure technique moderne consiste généralement à utiliser l’opérateur qr // (regex).

Je suis sûr que c’est toujours supporté, mais c’est à peu près obsolète. Si vous voulez que la regex soit compilée une seule fois, mieux vaut utiliser un object regex, comme ceci:

 my $reg = qr/foo$bar/; 

L’interpolation de $bar est effectuée lorsque la variable est initialisée. Vous utiliserez donc toujours la regex compilée en cache dans la scope englobante. Mais parfois, vous voulez que la regex soit recompilée, car vous voulez qu’elle utilise la nouvelle valeur de la variable. Voici l’exemple de Friedl utilisé dans The Book :

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

Dans le cadre de la fonction, la valeur de $ today_regex rest la même. Mais la prochaine fois que la fonction sera appelée, le regex sera recompilé avec la nouvelle valeur de $today . S’il venait juste d’utiliser

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

… le regex ne serait jamais mis à jour. Ainsi, avec la forme d’object, vous avez l’efficacité de / o sans sacrifier la flexibilité.

Le modificateur /o trouve dans la documentation de perlop au lieu de la documentation de perlre car il s’agit d’un modificateur de type devis plutôt que d’un modificateur de regex. Cela m’a toujours semblé étrange, mais c’est comme ça. Depuis Perl 5.20, il est maintenant répertorié dans Perlre simplement pour noter que vous ne devriez probablement pas l’utiliser.

Avant Perl 5.6, Perl recomstackrait le regex même si la variable n’avait pas changé. Vous n’avez plus besoin de faire ça. Vous pouvez utiliser /o pour comstackr la regex une fois malgré les modifications apscopes à la variable, mais comme le notent les autres réponses, qr// est préférable.

Dans la documentation Perl 5 version 20.0 http://perldoc.perl.org/perlre.html, il est indiqué

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

ce qui peut être une manière humoristique de dire qu’elle était censée effectuer une sorte d’optimisation, mais que l’implémentation est brisée.

Ainsi, l’option pourrait être mieux évitée.

Ceci est une optimisation dans le cas où l’expression régulière inclut une référence de variable. Cela indique que le regex ne change pas même s’il contient une variable. Cela permet des optimisations qui ne seraient pas possibles autrement.

Voici les horaires des différentes manières d’appeler les correspondances.

 $ 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 ]}, 

Mon code:

 #! /usr/bin/env perl use ssortingct; 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 } 

Une chose qu’elle ne fait pas mystérieusement, c’est autoriser un bloc ONCE, au moins à 5.8.8.

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