我想将正向引用与正则表达式匹配。我正在寻找的模式是
[snake-case prefix]_[snake-case words] [same snake-case prefix]_number
例如:
foo_bar_eighty_twelve foo_bar_8012
如果不首先查看foo_bar
,我就无法提取eighty_twelve
和foo_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支持那种模式。
有任何帮助吗?
答案 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 +包含下划线。而且我不认为这就是你想要的。