【发布时间】:2017-02-01 14:16:41
【问题描述】:
我有一个小问题。我有一个带有多个捕获组的 perl regexp。其中一些有量词(如'+')。如果未添加量词,则@- 和@+ 数组将很好地填充捕获组的匹配位置,但如果添加量词,则仅检测到最后一个匹配项。但我想拥有所有这些。
一个例子:
my $s = 'xx1a2b3cyy';
my $re = qr/^xx(\d\w)+/;
所以我想知道匹配是 '1a', '2b', '3c' 在 2、4、6。
简单匹配给出:
if ($s =~ $re) {
print "Match @-, @+\n";
for (my $i = 0; $i < @-; ++$i) {
print 'i: ', $i, " - '", substr($s, $-[$i], $+[$i] - $-[$i]), "\n";
}
}
给予:
Match 0 6, 8 8
i: 0 - 'xx1a2b3c
i: 1 - '3c
所以只有最后一次捕获组匹配被记住。
我的下一个简单尝试是这并不是我真正想要的,因为 RE 不同:
$re = qr/(\d\w)/;
my @s = ($s =~ /$re/g);
print "RE: '@s'\n";
while ($s =~ /$re/g) {
print "Match @-, @+\n";
for (my $i = 0; $i < @-; ++$i) {
print 'i: ', $i, " - '", substr($s, $-[$i], $+[$i] - $-[$i]), "\n";
}
}
给予:
RE: '1a 2b 3c'
Match 2 2, 4 4
i: 0 - '1a
i: 1 - '1a
Match 4 4, 6 6
i: 0 - '2b
i: 1 - '2b
Match 6 6, 8 8
i: 0 - '3c
i: 1 - '3c
但这不是我想要的,因为它会匹配像'ZZ1aAA2bBB3cZZ' 这样的字符串。
所以我必须以某种方式将两者结合起来。我能得到的最好的:
$re = '^xx(?:\d\w)*?\G(\d\w)';
pos($s) = 2;
while ($s =~ m($re)g) {
print "Match pos: ", pos($s), ', G: ', $1, ", '@-', '@+'\n"
}
给予:
Match pos: 4, G: 1a, '0 2', '4 4'
Match pos: 6, G: 2b, '0 4', '6 6'
Match pos: 8, G: 3c, '0 6', '8 8'
这几乎很好,但为此我需要知道第一个可能匹配的位置。如果设置不正确,它将不匹配任何内容。只有去掉非贪心部分才能确定第一个位置:
$re = '^xx(\d\w)';
if ($s =~ m($re)) {
print "Match: '@-', '@+'\n";
}
给出:
Match: '0 2', '4 4'
所以$-[1] 给出了第一个位置,但为此我必须“手动”修改 RE。
如果我将代码执行添加到模式中,我几乎可以得到我需要的东西:
use re 'eval';
$re = '^xx(\d\w)+(??{print "Code: <@-> <@+>\n"})';
$s =~ m($re) and print "Match\n";
给予:
Code: <0 6> <8 8>
Code: <0 4> <6 6>
Code: <0 2> <4 4>
为此,我需要添加(?{ code }) 部分。
有没有人知道更简单的方法(我的意思是不需要修改原始 RE)来获取具有量词的捕获组的所有可能匹配项?
提前致谢!
【问题讨论】:
-
my @matches = ( 'xx1a2b3cyy' =~ m/^xx(\d\w)+/ );仅包含3c。使用use re 'debug'告诉我们它得到1a、2b和3c每个作为子模式的匹配项,但我不知道它们最终会在哪里。看起来第一个子模式的最后一个匹配只保存为$1,这就解释了为什么@+和@-只指向它。 -
@simbabque 是的,这与小码给出的“简单匹配给出:”相同。无论如何,如果没有 'g' 修饰符,它不应该返回更多值。
-
但是如果你在我的例子中添加
/g,你也只能得到最后一个。 -
@simbabque:是的,你可以获得最后一场比赛,而不是全部。它对我没有帮助,因为我想拥有一切。似乎只有
(?{ code })可能会有所帮助...我必须检查它如何与带有量词的多个捕获组一起使用。