1

我继承了一些正则表达式并试图理解它为什么匹配某些模式。以下正则表达式基于积极的前瞻断言和匹配文本,如bear grylls episode. 这是有道理的。但它也匹配episode后面跟着的文本bear grylls,例如episode bear grylls。我在正则表达式中看不到任何向后看的参考。最后是.*?让它向后看吗?

^(?=.*?bear grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?
4

3 回答 3

0

这解释了它在做什么。
要修改,这取决于您要做什么。

这就是它目前正在做的事情——

 # ^(?=.*?bear\ grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?

 ^                             # Beginning of string
 (?=                           # Look ahead
      .*?                           # Ungreedy, any number of characters
      bear\ grylls                  # Must be 'bear grylls' somewhere
 )                             # End lookahead
 (?=                           # Look ahead
      .*?                           # Ungreedy, any number of characters
      (                             # (1 start), Must be one of these somewhere
           \b nbc \b 
        |  reality
        |  episode
        |  show
        |  watch
        |  series
        |  season
        |  premiere
      )                             # (1 end)
 )                             # End lookahead
 .*?                           # Assertions passed tests, now match the entire string

我会将其修改为此以获得更好的功能-

 # (?s)^(?=.*\bbear\ grylls\b)(?=.*\b(nbc|reality|episode|show|watch|series|season|premiere)\b).*

 (?s)                          # Dot all modifier
 ^                             # Beginning of string
 (?=                           # Look ahead
      .*                            # Greedy, any number of characters
      \b bear\ grylls \b            # Must be 'bear grylls' 
 )                             # End lookahead
 (?=                           # Look ahead
      .*                            # Greedy, any number of characters
      \b 
      (                             # (1 start), Must be one of these
           nbc 
        |  reality
        |  episode
        |  show
        |  watch
        |  series
        |  season
        |  premiere
      )                             # (1 end)
      \b 
 )                             # End lookahead
 .*                            # Assertions passed tests, now match the entire string

我建议在它格式化和创建自动评论的地方使用RegexFormat 5 。

于 2014-10-09T02:36:47.453 回答
0

所有前瞻和后瞻断言(?=...), (?!...), (?<=...),(?<!...) 不消耗文本。它不会将指针推进到当前位置,这是匹配某些文本时的正常行为。

由于它不推进索引,因此您可以利用此属性来检查文本的多个属性,否则很难在没有前瞻的情况下组合成一个表达式。

在您的情况下,正则表达式检查 string 是否存在bear grylls,然后在第二次预读中检查是否存在任何字符串。

如果没有前瞻,正则表达式将变为:

^.*?bear grylls.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)|^.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere).*?bear grylls

由于bear grylls可以在列表中的任何字符串之前之后出现,因此您需要交替检查这两种情况。DRY 问题可以通过字符串连接来解决,但是当它不可用时,人们将很难进行维护。

这也是密码验证中经常使用的一种技术,其中可以有多种条件,例如至少一个字母、至少一个数字、至少一个特殊字符、连续没有 3 个相同的字符等。如果你想写一个表达式来检查上面的所有属性,它非常混乱。使用前瞻断言可以让您将所有内容都塞进一个表达式中,而不会使正则表达式变得难以理解和难以维护。

就个人而言,我不太喜欢这种方法,因为将所有内容都塞进一个正则表达式是没有意义的,除非你受到工具的限制并且不允许运行多个正则表达式。我们可以只制作 2 个正则表达式并针对每个测试字符串。性能大致相同,因为在正则表达式引擎中完成了相同数量的工作。事实上,我相信大多数引擎会在上面的正则表达式中重新扫描字符串两次。

于 2014-10-09T02:42:46.767 回答
0

我重写了你原来的正则表达式,可以得到你想要的结果

^(?=.*?bear grylls).+(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?

它与上一个非常相似。唯一的区别是我在两个肯定的前瞻断言之间添加了“.+”,这将强制这两个部分的顺序,例如,“bear grylls episode”将产生肯定的结果,而“episode bear grylls”则不会。

没有这个,这两个前瞻断言将没有任何序列偏好。基本上它们是完全相等的。

于 2014-10-09T02:43:19.707 回答