我正在编写一个简单的正则表达式,它需要接收一对坐标和/或 map 名称。
例如:
move 10 15 # should returns [[10, 15]]
move 10 15 map # should returns [[10, 15, 'map']]
move map # should returns [['map']]
move 10 15 mapA mapB # should returns [[10, 15, 'mapA'], ['mapB']]
move 10 15 mapA mapB 33 44 # should returns [[10, 15, 'mapA'], ['mapB'], [33, 44]]
move 10 15 mapA 33 44 mapB # should returns [[10, 15, 'mapA'], [33, 44, 'mapB']]
然后,我写了这个正则表达式:
/
(?(DEFINE)
(?<coord> (?<x>\d+)\s+(?<y>\d+) )
(?<map> (?<mapname>[a-zA-Z]+) )
(?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
)
move\s+(?&commands)
/six
但是如何使用 Perl 获取组 x
、y
和 map
的值?
我尝试了一些方法:
use strict;
use warnings;
my $command = 'move 10 15';
$command =~ /
(?(DEFINE)
(?<coord> (?<x>\d+)\s+(?<y>\d+) )
(?<map> (?<mapname>[a-zA-Z]+) )
(?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
)
move\s+(?&commands)
/six;
while (my ($k,$v) = each %+) { print "$k $v\n" }
print "$+{x}";
最佳答案
就问题而言,你不能这样。 perlre说到这个
Note that capture groups matched inside of recursion are not accessible after the recursion returns, so the extra layer of capturing groups is necessary.
但模式 <x>
事后不能使用“额外的一层”捕获,因为它仅在语法内部使用。你只能拥有整个东西
if ($command =~ /
move\s+ (?<match>(?&commands))
(?(DEFINE)
(?<coord> (?<x>\d+)\s+(?<y>\d+) )
(?<map> (?<mapname>[a-zA-Z]+) )
(?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
)
/six)
{
say "got: $+{match}";
}
我将 ?(DEFINED)
移到了哪里按照建议,在模式末尾设置 block 。
请注意,这也没有任何意义:在递归匹配中,which of multiple <x>
应该得到吗?因此,您需要重新构建方法,以便能够重新捕获您想要的匹配;但如果你想把子模式埋得这么深,我不知道该怎么做。
对于提出的问题,我会编写一个简单的解析器,不要介意一个包罗万象的正则表达式。或者,在你的方法中重新处理匹配的部分,希望一旦你拥有它会更容易。
还有一些强大的工具,比如 Marpa::R2 , Parse::RecDescent , Regexp::Grammars .
关于regex - 如何在递归正则表达式中获得匹配的组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54860028/