我想知道在perl正则表达式中使用常量。我想做类似的事情:
use constant FOO => "foo"
use constant BAR => "bar"
$somvar =~ s/prefix1_FOO/prefix2_BAR/g;
当然,在那里,FOO
解析为三个字母F
O
O
,而不是扩展为常量。
我在线观看,有人建议使用${\FOO}
或@{[FOO]}
其他人提及(?{FOO})
。我想知道是否有人可以了解哪些是正确的,以及是否有任何优势。或者,使用非常量变量更好吗? (性能是我的一个因素)。
答案 0 :(得分:6)
在变量上使用常量的原因并不多。它没有太大的区别 - perl
无论如何都会编译一个正则表达式。
例如:
#!/usr/bin/perl
use warnings;
use strict;
use Benchmark qw(:all);
use constant FOO => "foo";
use constant BAR => "bar";
my $FOO_VAR = 'foo';
my $BAR_VAR = 'bar';
sub pattern_replace_const {
my $somvar = "prefix1_foo test";
$somvar =~ s/prefix1_${\FOO}/prefix2_${\BAR}/g;
}
sub pattern_replace_var {
my $somvar = "prefix1_foo test";
$somvar =~ s/prefix1_$FOO_VAR/prefix2_$BAR_VAR/g;
}
cmpthese(
1_000_000,
{ 'const' => \&pattern_replace_const,
'var' => \&pattern_replace_var
}
);
给出:
Rate const var
const 917095/s -- -1%
var 923702/s 1% --
真的不够担心。
然而,值得注意的是 - 您可以使用qr//
编译正则表达式并按照这种方式执行,只要RE是静态的 - 可能会提高性能(但它可能不会,因为perl 可以检测静态正则表达式,并自行完成。
Rate var const compiled
var 910498/s -- -2% -9%
const 933097/s 2% -- -7%
compiled 998502/s 10% 7% --
代码如下:
my $compiled_regex = qr/prefix1_$FOO_VAR/;
sub compiled_regex {
my $somvar = "prefix1_foo test";
$somvar =~ s/$compiled_regex/prefix2_$BAR_VAR/g;
}
老实说 - 这是微观优化。与您的代码相比,正则表达式引擎很快,所以不要担心它。如果性能对您的代码至关重要,那么处理它的正确方法是首先编写代码,然后对其进行分析以寻找要优化的热点。
答案 1 :(得分:4)
您显示的问题是由于这些常量是裸字(在编译时构建)
使用此模块定义的常量不能插入到变量等字符串中。
在“当前实施”(v5.24 docs)中,它们是无法使用的子程序。请参阅constant pragma。
等模块可以解决此问题use Const::Fast;
const my $foo => 'FOO';
const my $bar => 'BAR';
my $var = 'prefix1_FOO_more';
$var =~ s/prefix1_$foo/prefix2_$bar/g;
现在他们将被插值。请注意,更复杂的替换可能需要/e
。
这些是在运行时构建的,因此您可以将表达式的结果分配给它们。特别是,您可以使用qr operator,例如
const my $patt => qr/foo/i; # case-insensitive
qr
是构建正则表达式模式的推荐方法。性能增益通常很小,但是你得到一个常量,这是一个正确的正则表达式(并且可以这样构建)。
我使用这个模块并没有遇到任何问题。我很乐意推荐它。请参阅recent article并详细讨论两者。这是许多其他选项的review。
答案 2 :(得分:1)
根据PerlMonk的说法,如果您担心性能,最好创建一个已插入的字符串:
use constant PATTERN => 'def';
my $regex = qr/${\(PATTERN)}/; #options such as /m can go here.
if ($string =~ regex) { ... }
以下是whole discussion的链接。