【问题标题】:Is there a way to precompile a regex in Perl?有没有办法在 Perl 中预编译正则表达式?
【发布时间】:2010-10-31 11:31:38
【问题描述】:

有没有办法在 Perl 中预编译正则表达式?我有一个我在一个程序中多次使用它并且在使用之间不会改变。

【问题讨论】:

  • 对于更一般的替换情况,使用包含正则表达式和替换的变量(例如,替换像s/(\w+)/\u\L$1/g;(在变量/外部数据中),而不仅仅是变量中的固定字符串),请参阅@ 987654321@

标签: regex perl compilation


【解决方案1】:

使用 qr// 运算符(记录在 Regexp Quote-Like Operators 下的 perlop - Perl operators and precedence 中)。

my $regex = qr/foo\d/;
$string =~ $regex;

【讨论】:

  • 不错,它似乎可以用作 s/// 构造中的模式。在这种情况下它仍然是预编译还是再次编译?
  • @akostadinov 它仍然是预编译的。
【解决方案2】:

对于文字(静态)正则表达式,没有什么可做的——Perl 只会编译一次。

if ($var =~ /foo|bar/) {
    # ...
}

对于存储在变量中的正则表达式,您有几个选项。您可以使用qr// 运算符来构建一个正则表达式对象:

my $re = qr/foo|bar/;

if ($var =~ $re) {
    # ...
}

如果您想在多个地方使用正则表达式或将其传递给子例程,这很方便。

如果正则表达式模式在字符串中,您可以使用/o 选项向 Perl 承诺它永远不会改变:

my $pattern = 'foo|bar';

if ($var =~ /$pattern/o) {
    # ...
}

不过,通常最好不要这样做。 Perl 足够聪明,可以知道变量没有改变,也不需要重新编译正则表达式。指定/o 可能是过早的微优化。这也是一个潜在的陷阱。如果变量 has 使用/o 改变了会导致 Perl 使用旧的正则表达式。这可能会导致难以诊断的错误。

【讨论】:

  • 这些都是真的;但是,qr// 已经支持很多年了(从 5.005 开始就存在,我认为从 5.8 开始就没有问题了)
  • @ephemient 好吧,5.10 有一个与 qr// 相关的严重内存泄漏(通常是编译正则表达式),但这已得到修复。如果您使用的是 5.10,您可以通过说 perl -e 'qr// while 1' 来检查是否有内存泄漏。我知道 ActiveState Perl 5.10 的 OS X 版本仍然被破坏。
  • 2016 年的注意事项:/o 修饰符已被弃用。详情请见this question
  • 对于多个使用相同的预编译正则表达式,您可以使用 my $re = qr/foo|bar/ then next if ($var =~/something $re something/) 多次。它记录在 perlre
  • 我建议始终测量速度结果。永远不要相信“使用预编译的东西应该更快”的感觉。对我来说,在 perl 5.24.1 中使用 qr// 而不是仅在代码中使用正则表达式内联会使其速度降低 60% 以上!
【解决方案3】:

为了澄清,您可以使用预编译的正则表达式:

my $re = qr/foo|bar/;  # Precompile phase
if ( $string =~ $re ) ...   # For direct use
if ( $string =~ /$re/ ) .... # The same as above, but a bit complicated
if ( $string =~ m/something $re other/x ) ...  # For use precompiled as a part of a bigger regex
if ( $string =~ s/$re/replacement/ ) ...  # For direct use as replace
if ( $string =~ s/some $re other/replacement/x ) ... # For use precompiled as a part of bigger regex, and as replace all at once

perlre 中有记录,但没有直接的例子。

【讨论】:

  • 我不认为“使用预编译作为更大正则表达式的一部分”是真的。正则表达式不能由字符串组成。例如,考虑如果$re 之后的下一个字符是+ 会发生什么
  • 它取决于用于正则表达式的实现和标志。只有做一些基准和测试才能向我们展示编译器的真正作用。当 regexp 几乎没有编译时,更改 $re 值将不起作用。将使用旧的 $re 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 2013-02-26
  • 2021-07-21
  • 2021-03-19
  • 2019-02-24
  • 1970-01-01
  • 2019-06-28
相关资源
最近更新 更多