一次性存储所有正则表达式相关变量

时间:2015-06-29 20:20:20

标签: regex perl

简而言之

如何在另一个正则表达式的评估中保留$+$-$&$'等正则表达式变量?

/(\w)\s(\w)/ # First regex
say "Found a b" if $1 =~ /b/;
say "$1, $2" # Match from the first regex

详情

对于小型解析器,我想评估两个级联。第一个标识标记,第二个标记获取标记的性质。

所以我写了这个:

my $out = '';
while(/\{\{(?<tag>.*?)\}\}/g) {   
    if($+{tag} =~ /^\#(?<helper>\w+)\s+(?<parameters>.*)$/) {
        # Do something
    }

    $_ = $`.($data{$+{tag}} // $+{tag}).$';
}

在这种特殊情况下,我想在执行另一个正则表达式后使用第一个正则表达式的结果,这个正则表达式破坏了正则表达式变量($+$-$&,{{1 },...)。

我知道我可以让这个例子使用如下所示的中间存储。然而,这不是这个问题的主要话题。

$'
  

所以,我想知道我是否可以简单地说:

     
      
  1. 避免第二个正则表达式破坏正则表达式变量,或
  2.   
  3. 一次保存所有相关的正则表达式变量?
  4.   

我不是在讨论这里使用的实现或方法。只有上述问题才有意义。

只为好奇而

以下是我解析个代码的方法。下一步将解析帮助程序,列表和哈希键,并尽可能简化所有内容......

push @regex, {match => $&, prematch => $`, #... 
};

3 个答案:

答案 0 :(得分:3)

Regexp::Result会捕获$1$2pos以及所有优秀的标点符号变量,看起来就像您需要的那样。 (它不会捕获效率低下的标点符号变量$&$'和美元反引号,因为如果您在任何地方使用它们,都会导致所有正则表达式匹配产生性能损失。)

对于while循环,您可能还会发现Regexp::Flow非常有用,具体取决于您最终在该循环中执行的操作。它为您创建Regexp :: Result对象并将它们传递给coderef。

披露:我是两个模块的作者

如果您需要它们,可以使用${^MATCH}${^PREMATCH}${^POSTMATCH}而不是三个效率低下的变量,只要您在执行时使用/p标记即可正则表达式。使用Regexp :: Result,您可以使用$rr->match等获取它们

为了完整性,如果您只需要编号的捕获而不需要其他内容,Data::Munge会提供一个函数submatches

答案 1 :(得分:3)

正则表达式变量已本地化到它们出现的块中,因此只需将第二个正则表达式嵌套在一个块中:

$_ = 'b c';
/(\w)\s(\w)/; # First regex
{
    say "Found a b" if $1 =~ /b/;
}
say "$1, $2" # Match from the first regex

或最低限度地使其成为...if do { $1 =~ /b/ };

答案 2 :(得分:0)

我不熟悉把手,但似乎使用可选的非捕获组可以简化您的代码:

use strict;
use warnings;
use 5.010;

while (<DATA>) {
    my ($tag, $helper, $params) = $_ =~ /{{ (\w+) (?: \s+ (\w+) \s+ (\w+) )? }}/gx;

    say $helper if defined $helper;
    say $params if defined $params;
}

__DATA__
{{foo}}
{{foo bar baz}}