正则表达式环顾四周 - Java

时间:2014-10-09 01:41:33

标签: regex lookahead lookaround

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

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

3 个答案:

答案 0 :(得分: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格式化并创建自动评论。

答案 1 :(得分:0)

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

由于它不会使索引前进,因此您可以使用此属性来检查文本的多个属性,否则很难将它们组合成单个表达式而不进行预读。

在你的情况下,正则表达式检查是否存在字符串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个正则表达式并测试每个字符串。性能大致相同,因为在正则表达式引擎中完成了相同的工作量。事实上,我相信大多数引擎会在上面的正则表达式中重新扫描字符串两次。

答案 2 :(得分:0)

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

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

它与前一个非常相似。唯一的区别是我添加&#34;。+&#34;在两个积极的先行断言之间,这将强制执行这两个部分的顺序,例如,&#34;承担grylls剧集&#34;将会有积极的结果,而#34;情节会伴随着#34;韩元&#39;吨。

如果没有这个,这两个前瞻断言不会有任何序列偏好。基本上他们是完全平等的。