2014-10-09 20 views
1

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

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

看看http://regex101.com,这给你输入正则表达式的正确解释 – radar 2014-10-09 02:03:31

回答

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它格式化,并创建自动评论。

+0

谢谢Sln。 如何用。* help替换。* *?贪婪的比赛不是比懒惰比赛更昂贵吗? – 2014-10-09 04:29:17

+0

它比较便宜。在断言中,如果可以的话,避免使用这个'。*?'结构。 – sln 2014-10-09 14:54:38

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

+0

谢谢nhahtdh,这澄清了关于位置的混淆。 如果我理解正确,比第二个选项更便宜。纠正我,如果它不正确。 – 2014-10-09 04:24:11

+0

@KaushalPatel:哪个第二选项?如果你在没有预见的情况下讨论漫长的正则表达式,那么这可能是事实。但是如果你正在谈论使用多个正则表达式,那么两者应该差不多。 – nhahtdh 2014-10-09 04:37:34

0

我改写原来的正则表达式,它可以有你想要的结果

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

这是很相似的前一个。唯一的区别是,我在两个肯定的前瞻断言之间加上了“+”,这将强制执行这两部分的顺序,例如,“bear grylls episode”将有积极结果,而“episode bear grylls”不会。

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

+1

这不符合你的想法。 '^(?=。*?熊格里尔斯)'仍然匹配字符串中的任何地方。 – sln 2014-10-09 02:47:05