Perl正则表达式前向引用

时间:2014-08-15 11:59:11

标签: regex perl reference

我想将正向引用与正则表达式匹配。我正在寻找的模式是

[snake-case prefix]_[snake-case words] [same snake-case prefix]_number

例如:

foo_bar_eighty_twelve foo_bar_8012

如果不首先查看foo_bar,我就无法提取eighty_twelvefoo_bar_8012。因此,我需要一个前向引用,而不是一个后向引用,只有当我的前缀不是一个蛇形前缀时才能工作。

my $prefix = "foo";
local $_ = "${prefix}_thirty_two = ${prefix}_32";

# Backward reference that works with a prefix with no underscores
{
    /(\w+)_(\w+) \s+ = \s+ \1_(\d+)/ix;
    print "Name: $2 \t Number: $3\n";
}

# Wanted Forward reference that do not work :(
{
    /\2_(\w+) \s+ = \s+ (\w+)_\d+/ix;
    print "Name: $1 \t Number: $2\n";
}

不幸的是,我的前向引用不起作用,我不知道为什么。我读过Perl支持那种模式。

有任何帮助吗?

2 个答案:

答案 0 :(得分:2)

以下假设是错误的:

  

“如果不首先查看foo_bar_8012,我无法提取foo_bar和eighty_twelve。”

是的,确实无法确定在第一组字符中出现前缀和名称中断的位置,直到查看第二组,但这样才能获得正则表达式的强大功能。它在第一次传递时贪婪地匹配,发现第二个字符串不匹配,然后回溯再次尝试使用较小的字符串作为前缀。

以下内容演示了如何使用简单的反向引用来实现目标:

use strict;
use warnings;

while (<DATA>) {
    if (m{\b(\w+)_(\w+)\s+\1_(\d+)\b}) {
        print "Prefix = $1, Name = $2, Number = $3\n";
    } else {
        warn "Not found: $_"
    }
}
__DATA__
foo_thirty_two foo_32
foo_bar_eighty_twelve foo_bar_8012

输出:

Prefix = foo, Name = thirty_two, Number = 32
Prefix = foo_bar, Name = eighty_twelve, Number = 8012

答案 1 :(得分:0)

AFAIK Forward referencing不是允许交换捕获组和引用的神奇子弹。

我看了很多例子,我根本不认为你可以使用前向引用来做你正在尝试的事情。

我通过使用反向引用和预测来解决了这个问题。像这样:

/(?=.*=\s*([a-z]+))\1_(\w+) \s+ = \s+ \w+_\d+/ix

这是有效的,因为预测会在&#34;实际&#34;之前初始化第一个捕获组。表达。作为参考,这部分是预见:

(?=.*=\s*([a-z]+))

它基本上只是一种&#34; sub-regex&#34;。我使用[a-z] +的原因是因为\ w +包含下划线。而且我不认为这就是你想要的。