为什么@+ 和@{^CAPTURE} 的长度不同?

rub*_*ion 5 regex perl

我试图了解正则表达式变量是如何工作的,因此我可以在嵌入式代码表达式中保存有效负载中的子匹配位置。根据perlvar,数组的正索引对应于 $1、$2、$3 等,但情况似乎并非如此?

#!/usr/bin/perl -w
use v5.28;
use Data::Dumper;

"XY" =~ / ( (.*) (.) (?{ 
    say Dumper { match_end => \@+ };
    say Dumper { capture => \@{^CAPTURE} }
}) ) (.)/x;
Run Code Online (Sandbox Code Playgroud)

输出

$VAR1 = {
          'match_end' => [
                           2,
                           undef,
                           1,
                           2,
                           undef
                         ]
        };

$VAR1 = {
          'capture' => [
                         undef,
                         'X',
                         'Y'
                       ]
        };

$VAR1 = {
          'match_end' => [
                           1,
                           2,
                           0,
                           1,
                           undef
                         ]
        };

$VAR1 = {
          'capture' => [
                         'XY',
                         '',
                         'X'
                       ]
        };
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 5

@+数组显然已在编译时分配或以其他方式准备

perl -MData::Dump=dd -we'$_=q(abc); / (?{dd @+})  ( (.) )/x'
Run Code Online (Sandbox Code Playgroud)

印刷

(0, undef, undef)

(整个匹配undef为0,每个指定的捕获组为 1),而

perl -MData::Dump=dd -we'$_=q(abc); / (?{dd @+})  ( (.) (.) )/x'
Run Code Online (Sandbox Code Playgroud)

印刷

(0, undef, undef, undef)

多一个元素用于多一个捕获组。

另一方面,@{^CAPTURE}正如我们从 mob 的详细分析中看到的那样,在有实际模式要捕获之前,它只是空的。我想说,这与它的名字很搭。

在数组同意这一事实之后,索引中的 1 的移动@+也包含(偏移)整个匹配, at $+[0]

另一个区别是尾随失败的可选匹配不会在 @{^CAPTURE}

perl -MData::Dump=dd -we'$_=q(abc); /((x)? (.) (x)?)/x; dd @+; dd @{^CAPTURE}'
Run Code Online (Sandbox Code Playgroud)

印刷

(1, 1, undef, 1, undef)
("a", undef, "a")


mob*_*mob 3

perlvar 文档不清楚@{^CAPTURE}正则表达式求值过程中的情况,但有一个明显的进展,具体取决于您在正则表达式中查看的位置。

use 5.026;
use Data::Dumper; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Indent = 0;

sub DEBUG_CAPTURE { say Dumper { a => $_[0], capture => \@{^CAPTURE} }; }

"XY" =~ /
   (?{DEBUG_CAPTURE(0)})
   (
     (?{DEBUG_CAPTURE(1)}) 
     (
             (?{DEBUG_CAPTURE(2)})
        (.*) (?{DEBUG_CAPTURE(3)}) 
         (.) (?{DEBUG_CAPTURE(4)}) 
     ) 
     (?{DEBUG_CAPTURE(5)}) (.)
     (?{DEBUG_CAPTURE(6)})  
   )
   (?{DEBUG_CAPTURE(7)})    /x;    
DEBUG_CAPTURE(8);
Run Code Online (Sandbox Code Playgroud)

输出

$VAR1 = {'a' => 0,'capture' => []};
$VAR1 = {'a' => 1,'capture' => []};
$VAR1 = {'a' => 2,'capture' => []};
$VAR1 = {'a' => 3,'capture' => [undef,undef,'XY']};
$VAR1 = {'a' => 3,'capture' => [undef,undef,'X']};
$VAR1 = {'a' => 4,'capture' => [undef,undef,'X','Y']};
$VAR1 = {'a' => 5,'capture' => [undef,'XY','X','Y']};
$VAR1 = {'a' => 3,'capture' => [undef,'XY','','Y']};
$VAR1 = {'a' => 4,'capture' => [undef,'XY','','X']};
$VAR1 = {'a' => 5,'capture' => [undef,'X','','X']};
$VAR1 = {'a' => 6,'capture' => [undef,'X','','X','Y']};
$VAR1 = {'a' => 7,'capture' => ['XY','X','','X','Y']};
$VAR1 = {'a' => 8,'capture' => ['XY','X','','X','Y']};
Run Code Online (Sandbox Code Playgroud)

@{^CAPTURE}如果您在正则表达式完全评估后进行观察,那么这些文档是正确的。虽然评估正在进行中,但@{^CAPTURE}似乎随着遇到的捕获组数量的增加而增加。@{^CAPTURE}但至少在读到表达式末尾之前,尚不清楚查看有多大用处。