Regex 如何强制Perl重新编译一个使用“quot/o";随需应变?
技术问题:Regex 如何强制Perl重新编译一个使用“quot/o";随需应变?,regex,perl,compilation,modifier,Regex,Perl,Compilation,Modifier,技术问题: $ 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++) {
$ 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
给定正则表达式:
my $regEx = qr{whatever$myVar}oxi; # Notice /o for "compile-once"
强制它按需重新编译的最有效方法是什么?(例如,当我从程序逻辑中知道,$myVar
值已更改)而不删除/o
,并且依靠Perl的内部智能自动重新编译
注意:正则表达式用于替换,这可能会影响重新编译规则SAN/o:
$string2 =~ s/$regEx//;
上下文是:
$ 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
- 我有一个正则表达式,它是通过从配置文件中拖入相当长(>1k长)的字符串来构建的
- 该文件每60分钟重新读取一次
- 如果从文件中读取的字符串发生更改(如通过更改文件时间戳定义的),我想使用
中重新编译的字符串值重新编译正则表达式$myVar
- 在mod_Perl下运行的Perl模块中,regex经常重复使用
- 这意味着(再加上长度>1-2k的字符串)我必须使用“
”修饰符在正则表达式上强制编译一次,以避免Perl重复检查变量值是否更改的性能影响(由于正则表达式是如上所示的/o
的一部分,而不是单独作为匹配项使用,因此此启发式方法来自)s//
- 这反过来意味着,当我知道变量在1小时内重新slurp后发生了变化时,我需要强制正则表达式重新编译,尽管有
修饰符/o
- 这意味着(再加上长度>1-2k的字符串)我必须使用“
/o
-没有它,正则表达式在每次循环迭代中都会重新编译(因此必须进行检查);没有它:
$ 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
$perl-e'{for(my$i=0;$i您基本上回答了自己的问题。使用qr{…}
创建一个已编译的regexp对象,然后使用它:
my $re = qr{...};
...
if ($str =~ $re) {
# this used the statically compiled object
}
...
if ($time_to_recompile) {
$re = qr{...};
}
您甚至不需要“/o”修饰符。当我从程序逻辑知道$myVar值已更改时
m/
、s//
和qr/
只有在模式不变的情况下才能编译。要获得所请求的行为,只需删除/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"
所以,
如果从文件中读取的字符串发生更改(如更改文件时间戳所定义的),我希望使用$myVar中重新编译的字符串值重新编译正则表达式。
或者只是
$myVar = ...;
...
s/$myVar/.../
据perlop说
“o”修饰符的效果不是
传播的,仅限于那些
模式显式地使用它
所以如果你写
my $str = 'x';
my $re = qr/$str/o;
...
if (s/$re//) {
...
}
Perl在执行s//
时仍会检查$re
是否已更改。/o
承诺编译$re
时使用的$str
值不会更改,因此,如果重新执行qr/
,即使$str
已更改,也会得到相同的结果ged。您可以在使用“重新调试”时看到这一点:
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//;
}
使用/o
修饰符,在循环的第一次“设置$re”之后,您只能看到“编译REx…”。没有它,您将在每次迭代中看到它
需要注意的是,如果您想在运行时更改模式,则不应使用/o
。这不会影响s///
,并且会阻止您在需要时重新编译$re
。我认为这不起作用。您代码中的第二个块经常执行,而且据我所知g它会尝试检测插值变量的值是否每次都改变。@Nemo-我现在知道问题出在哪里了。我忽略了提到我代码中的正则表达式不是以纯$str=~$re
的方式使用的,而是以一种替代方式使用的:$str=~s/$re/
。除非我不理解文档,否则这意味着正则表达式将被重新使用在没有/o
的情况下编译每个替换,即使您给出的代码示例不会。我用示例用法更新了Q。我不这么认为。但是尝试一个实验很容易…设置$re=qr{…}
其中,..
取决于某个字符串$s
,然后修改$s
,然后执行s/$re/
。如果它使用原始字符串,则最好将其编译。最坏的情况下,只需使用/o
,如我的$re=qr{…}/o
中所述。当您要重新编译时,只需分配$re=qr{…}/o
@DVK:当然可以——每次循环都显式地重新编译正则表达式。