Perl 6:提前捕获

Jo *_*ing 10 regex perl6 regex-lookarounds raku

我正在尝试为此代码高尔夫挑战编写一个Perl 6正则表达式,该挑战用规则拆分字符串:

  • 长度小于等于3的相同字符的序列将被分组在一起
  • 但是4个或更多将导致在检查其余两个之前将前两个分组

例如:

66667888    -> '66', '66, '7', '888'
19999999179 -> '1', '99', '99', '999', '1', '7', '9'
Run Code Online (Sandbox Code Playgroud)

我以为正则表达式m:g/(.)[$0$0<!$0>|$0?]/可以正常工作,但是在负前瞻中使用捕获似乎会破坏它,而且我不知道如何正确使用它。

根据我的使用方式,它会永远循环,抛出错误 Cannot resolve caller INTERPOLATE_ASSERTION返回错误的结果。有没有适当的方法可以提前使用捕获,或者这是一个错误?

Wik*_*żew 6

根据捕获部分,您需要使用代码块使这些反向引用在正则表达式中可见:

这些捕获变量仅在正则表达式外部可用。为了使它们在正则表达式内部可用,您需要在匹配项后面插入一个代码块。如果没有任何意义可做,则此代码块可能为空

使用

given "19999999179" {
  for m:g/(.) {} :my $c = $0; ([ $c$c<!$c> | $c? ])/  -> $match {
    say ~$match;
  }
}
Run Code Online (Sandbox Code Playgroud)

结果:

1
99
99
999
1
7
9
Run Code Online (Sandbox Code Playgroud)

参见Perl6演示

在这种情况下,您可以将模式压缩为m:g/(.) {} [ $0$0<!$0> | $0? ]/

my @matches;
given "19999999179" {
  for m:g/(.) {} [ $0$0<!$0> | $0? ]/ -> $match {
    @matches.push: (~$match);
  }
}
say @matches;
Run Code Online (Sandbox Code Playgroud)

结果[1 99 99 999 1 7 9]

请参阅此Perl6演示

  • 仅供参考,对于打高尔夫球,也许还有更多的速度和可读性,您可以简化为`m:g /(。)$ 0?[$ 0 {} &lt;!$ 0&gt;]?/`,删除`$ 0`和`|`交替(更好的高尔夫方式),并将`{}`放在当前需要它的构造(`&lt;!$ 0&gt;`)之前,以提高可读性,也许微小的加速。 (2认同)