【问题标题】:Perl match variables and performance. How does it work?Perl 匹配变量和性能。它是如何工作的?
【发布时间】:2016-10-04 15:51:13
【问题描述】:

根据perlvar

与正则表达式相关的变量

这些变量是只读的 并且是动态范围的,除非我们另有说明。动态性质 的正则表达式变量意味着它们的值是有限的 到他们所在的街区。

再往下:

传统上,在 Perl 中,任何使用三个变量中的任何一个 $` , $&$' 代码中的任何位置,导致 所有后续成功的模式匹配以复制 匹配的字符串,以防代码随后访问其中之一 那些变量。

从文档中阅读了该部分的其余部分后,我仍然错过了一些信息,例如:

  • 为什么首先要制作副本?

    我想我知道这个问题的答案:从上一条声明"in case the code might subsequently access one of those variables" 中可以清楚地看出这一点。 所以在我的理解中:

    my $s = "Hello world";
    $s =~ s/Hello //;
    say $';
    

    这仍然会打印 world,因为在修改 $s 之前已制作了副本。

  • 为什么要复制整个字符串?

    在前面的示例中,只复制字符串的尾部就足够了,因为只使用了$'(我们没有使用$`$&)。那么为什么要复制整个字符串呢?

  • 最后:既然是"all subsequent" 而不是"all subsequent matches in that block",我想确认一下:

    my $s = "no\n yesHello world";
    {
        $s =~ /yes/ and say $'; # Note the use of $'
    }
    $s = '12' x 1_000_000;
    my $n = () = $s =~ /2/g;
    say "Found $n matches";
    

    在这种情况下,(因为$' 仅用于内部范围)不会与$s =~ /2/g 中的一百万个成功匹配相关的复制? (假设我没有在外部范围内提及$`$&$'


注意

  • 问题假设 perl 版本低于 5.18。 根据perlvar

    从 Perl 5.18.0 开始,perl 开始记录每个 三个变量分开,并且只复制了那部分 需要字符串

    在 Perl 5.20.0 中,默认启用了新的写时复制系统, 最终解决了这三个变量的所有性能问题, 并让它们在任何地方都可以安全使用。

  • 我只是出于好奇才问这个问题。我不打算在我的代码中实际使用任何这些变量,因为我希望我的程序也能有效地为早期的 perl 版本(

    此外,如手册中所述,可以使用 $+[0]$-[0](在 perl 5.6 版中引入。我自己使用 perl 5.22 版)轻松模拟它们(没有隐式复制和性能损失) .请参阅perlvar 了解更多信息。

【问题讨论】:

  • 在 5.20 之前,您可以使用 /p 或捕获。

标签: perl


【解决方案1】:
  • 它必须复制字符串,因为原始变量可能在正则表达式匹配和使用匹配变量的时间之间被修改:

    my $var = "foobar";
    $var =~ /.../ or die;
    $var = "hello";
    print "$& $'";  # outputs "foo bar"
    
  • 它必须有效地复制整个字符串,因为这就是$` . $& . $' 的结果。正如你自己引用的那样,在 perl 5.18 中有人意识到你可以单独跟踪每个变量,因此只复制匹配之前的部分(或匹配本身,或匹配后的部分),如果代码中仅出现该变量:

    从 Perl 5.18.0 开始,perl 开始分别记录这三个变量中每一个的存在,并且只复制了所需的字符串部分

  • 匹配变量是全局的。您可以随时调用访问$`$&$' 的函数(调用调用函数的函数...),因此perl 必须在每次成功的正则表达式匹配后进行完整复制,如果那些在代码中的任何地方都可以看到变量。 (基本上,perl 不能静态地确定一段特定的代码永远不会访问那些匹配变量,从而避免复制。)

【讨论】:

    猜你喜欢
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多