【问题标题】:Negative lookahead not working after character range with plus quantifier带有加量词的字符范围后负前瞻不起作用
【发布时间】:2018-03-09 13:31:29
【问题描述】:

我正在尝试实现一个正则表达式,其中包含所有具有任意数量的单词但后面不能跟 : 的字符串,如果匹配则忽略匹配。我决定对它使用负面的展望。

/([a-zA-Z]+)(?!:)/gm
string: lame:joker

因为我使用的是字符范围,它一次匹配一个字符,并且只忽略 : 之前的最后一个字符。 在这种情况下如何忽略整个匹配?

正则表达式101的链接:https://regex101.com/r/DlEmC9/1

【问题讨论】:

    标签: python regex regex-lookarounds


    【解决方案1】:

    + 之后执行单词边界检查\b 以要求它到达单词的末尾。

    ([a-zA-Z]+\b)(?!:)
    

    Here's an example run.

    【讨论】:

      【解决方案2】:

      问题与回溯有关:一旦您的[a-zA-Z]+ 变为:,引擎就会从失败的位置退回,重新检查前瞻匹配并在任何时候找到匹配冒号前至少有两个字母,返回没有紧跟: 的那个。参见your regex democ:real 中的c 不匹配,因为没有可回溯到的位置,而real:c 中的rea 匹配,因为a 没有紧跟:

      向否定前瞻添加隐式要求

      由于您只需要匹配不带冒号的字母序列,因此您可以显式添加一个隐含的条件:并且不带另一个字母

      [A-Za-z]+(?![A-Za-z]|:)
      [A-Za-z]+(?![A-Za-z:])
      

      请参阅regex demo。由于[A-Za-z]: 都匹配单个字符,因此将它们放入单个字符类是有意义的,因此[A-Za-z]+(?![A-Za-z:]) 更好。

      使用单词边界防止回溯到类似单词的模式

      正如@scnerd suggests,单词边界在这些情况下也有帮助,但总有一个问题:单词边界的含义取决于上下文(参见word boundary explanation 中的许多ifs)。

      [A-Za-z]+\b(?!:)
      

      在这里是一个有效的解决方案,因为输入暗示单词以非单词字符结尾(即字符串结尾,或除字母、数字和下划线以外的字符)。请参阅regex demo

      单词边界什么时候失效?

      \b 将不是正确的选择,当主要消费模式应该匹配时,即使粘在其他单词字符上。最常见的例子是匹配数字:

      • \d+\b(?!:) matches 1212, 中,但不在 12: 中,还有 12c12_
      • \d+(?![\d:]) matches 1212, 12c12_,不只在12: 中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-23
        • 2020-06-11
        • 1970-01-01
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 2018-02-02
        • 1970-01-01
        相关资源
        最近更新 更多