【问题标题】:Perl fails stating `Variable length lookbehind not implemented`Perl 未能说明“未实现可变长度后视”
【发布时间】:2013-11-21 05:24:39
【问题描述】:

我基本上是在做一种词边界断言。我想测试[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;

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    lookbehind 节点只是查看它的子节点,发现它包含一个命名的子规则匹配,并确定一个命名的子规则匹配不一定是固定长度的。它不会查看命名子规则的内部以发现它实际上确实具有固定长度,我不确定它是否可以给出代码的当前状态。由于无法确定固定长度,因此无法编译lookbehind。

    也许消息应该是Can't determine the length of '(?&amp;W)' for use in lookbehind而不是Variable length lookbehind not implemented

    【讨论】:

    • 那真是太烦人了。 :( 我把这个给你,因为你得到了赞成票。我已经把它作为缺陷提交了。
    【解决方案2】:

    好像就在这里:

    (?<=(?&W))(?=(?&NW))
        |(?<=(?&NW))(?=(?&W))
    

    在 Perl 5 中,正则表达式不支持在后面查找可变数量的捕获(() 中的内容)。

    ?

    编辑:下面的评论可以澄清问题。

    看起来你拥有的可变长度是因为你有一个 [^abc] 的命名模式,它有大量可以返回的匹配长度。可变长度来自于任何长度的文本都可以匹配!abc的字符类。

    Perl 6 似乎以某种方式支持这一点。

    有关此问题,请参阅 Perl 6 的 RFC 链接 http://perl6.org/archive/rfc/72.html

    【讨论】:

    • 谢谢,我知道它在哪里,我知道它意味着什么。据我所知,这两段代码应该是等价的。具体来说,它是由(?&lt;=(?&amp;NW)) 引起的,但我不知道为什么它应该是失败的。它是由(?&lt;NW&gt;[^abc]) 定义的非可变长度模式。
    • 您似乎对这个问题有很好的理解,但您很困惑为什么一个有效而另一个无效?这是 Perl 版本的东西。
    • 什么是Perl 版本的东西
    • 抱歉,这意味着您使用的 Perl 版本不支持您尝试使用的操作。看起来你所拥有的可变长度是因为你有一个 [^abc] 的命名模式,它有大量可以返回的匹配长度。
    • 这是一个缺陷吗?是否有任何文件表明不应该这样做?
    【解决方案3】:

    命名捕获的匹配并不总是固定长度,这就是正则表达式引擎不允许将反向引用放在后面的原因。名为 capture 的变长示例:

    /(?|a(?<toto>ef)|b(?<toto>ghi))/
    

    【讨论】:

    • 但是对可变长度的测试是可行的,因为当它不是命名表达式时,它目前已经完成,那么为什么不完成呢?另外,你的例子不太好。请说清楚。谢谢。
    • @Adrian:我真的不知道,我不是正则表达式引擎开发者!但霍布斯的回答是我想象的那种情景。我不认为这是一个错误,而是一个限制(作为固定长度后视)
    【解决方案4】:

    对我来说看起来像一个错误,但错误的解决方案可能只是有一个单独的错误消息“未实现递归捕获组lookbehind”:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-09
      • 2010-09-12
      • 2012-08-04
      • 2020-03-15
      • 2021-08-17
      • 1970-01-01
      相关资源
      最近更新 更多