Perl报错:Variable length lookbehind not implemented。

5

我基本上正在制作一种单词边界断言。我想测试如果[abc]不在后面,如果[abc]在前面,并反之亦然。

所以我试图进行测试并像这样否定:

#!/usr/bin/perl
($_) = "abcdef" =~
/
((?&BB).*)
|
  (?!)
  (?<W>[abc])
  (?<NW>[^abc])
  (?<BB>
     (?<=(?&W))(?=(?&NW))
    |(?<=(?&NW))(?=(?&W))
  )
/x;
print;

这不起作用。 但是,如果我这样做:

#!/usr/bin/perl
($_) = "abcdef" =~
/
  ((?&BB).*)
| (?!)
  (?<W>[abc])
  (?<NW>[^abc])
  (?<BB>
      (?<=[abc])(?=[^abc])
    | (?<=[^abc])(?=[abc])
  )
/x;
print;

确实如此。 发生了什么? 变长回溯在哪里?

顺便说一句,我知道这个消息的意思。 我想知道为什么perl认为命名组是可变长度的,我该怎么做才能让它停止这样想呢? 对我来说,这似乎是一个错误。 有其他人同意吗?

使用版本:

This is perl 5, version 14, subversion 4 (v5.14.4) built for cygwin-thread-multi
This is perl 5, version 16, subversion 2 (v5.16.2) built for i686-linux

编辑

所以我找到了一个足够好的解决办法。

#!/usr/bin/perl
$chars = qr/[abc]/;
$notChars = qr[^abc]/;
($_) = "abcdef" =~
/
  ((?&BB).*)
| (?!)
  (?<BB>
      (?<=$chars)(?=$notChars)
    | (?<=$notChars)(?=$chars)
  )
/x;
print;
4个回答

9

回顾节点只是查看其子级,看到它包含一个命名子规则匹配,并决定命名子规则匹配不一定是固定长度。 它不会查看命名子规则中的内容以找出它实际上具有固定长度,我不确定在当前代码状态下是否可以这样做。 由于无法确定固定长度,因此无法编译回顾。

也许消息应该是类似于无法确定'(?&W)'的长度以用于回顾,而不是未实现可变长度回溯


好烦啊。:( 我把这个交给你,因为你得到了赞。我已经将其提交为缺陷。 - Adrian

2
看起来它在这里:
(?<=(?&W))(?=(?&NW))
    |(?<=(?&NW))(?=(?&W))

在Perl 5中,正则表达式不支持变量数量的回溯捕获(括号中的内容)。
?<=和括号中的内容是回溯语法的位置。
编辑:下面的评论引导了问题的澄清。
看起来你所拥有的可变长度是由于你有一个命名为[^abc]的模式,它具有各种可能的匹配长度。变量长度来自于任何长度的文本都可以与!abc字符类匹配。
Perl 6似乎以某种方式支持这一点。
请参见此链接,了解有关此问题的Perl 6 RFC http://perl6.org/archive/rfc/72.html

谢谢,我知道它在哪里,也知道它的意思。据我所知,这两段代码应该是等价的。具体来说,问题出在(?<=(?&NW))这一行,但我不知道为什么会失败。它是由(?<NW>[^abc])定义的非固定长度模式。 - Adrian
似乎您对这个问题有很好的理解,但不知道为什么一个可行而另一个不行?这是由于Perl版本的原因。 - Ryan J
什么是“Perl版本的东西”? - Adrian
抱歉,这意味着您使用的Perl版本不支持您尝试使用的操作。看起来,您拥有的变量长度是由于您拥有一个命名模式[^abc]的事实固有的,该模式具有各种各样的匹配长度可以返回。 - Ryan J
那这是一个缺陷吗?有没有任何文件说明它不应该这样? - Adrian

1
一个命名捕获的匹配并不总是具有固定的长度,这就是为什么正则表达式引擎不允许在后顾中放置反向引用的原因。以下是变长命名捕获的示例:
/(?|a(?<toto>ef)|b(?<toto>ghi))/

但是,如果它不是命名表达式,测试变量长度是可行的,因此为什么不这样做呢?另外,您的示例不太好,请澄清一下。谢谢。 - Adrian
@Adrian:我真的不知道,我不是正则表达式引擎开发人员!但是Hobbs的答案是我想象中的一种情况。我认为这不是一个bug,而是一个限制(就像固定长度的后瞻)。 - Casimir et Hippolyte

1

对我来说看起来像是一个bug,但解决这个问题的方法可能只是提供一个单独的错误信息“未实现递归捕获组后置断言” :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接