regex - 如何在递归正则表达式中获得匹配的组?

标签 regex perl regex-recursion

我正在编写一个简单的正则表达式,它需要接收一对坐标和/或 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 获取组 xymap 的值?

我尝试了一些方法:

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/

相关文章:

javascript - 正则表达式条件不适用于 polymer 纸张输入,如何在纸张输入上仅允许小数?

regex - Text.Regex.Applicative - 多行注释

Python 正则表达式 - 匹配和 Start()

perl - 在哪里可以找到将现有 CPAN 模块转换为使用 Dist::Zilla 的简明指南?

正则表达式递归 : Nth Subpatterns

java - 在 Java 中将字符串 String 与大型正则表达式列表、性能进行匹配

perl - 如果我的字符串包含 's///' ,我该如何使用 '/' ?

regex - 这个递归正则表达式究竟是如何工作的?

perl - 在 Windows 上使用 perl 合并 PDF 文件