Regex环顾四周-Java
我继承了一些正则表达式,并试图理解它为什么匹配某些模式。下面的正则表达式是基于积极的前瞻断言和匹配文本,如Regex环顾四周-Java,regex,lookahead,lookaround,Regex,Lookahead,Lookaround,我继承了一些正则表达式,并试图理解它为什么匹配某些模式。下面的正则表达式是基于积极的前瞻断言和匹配文本,如熊格里尔的插曲。这是有道理的。但它也匹配插曲后面跟着熊格里尔斯的文本,例如插曲熊格里尔斯。我在正则表达式中没有看到任何向后看的参考。最后的*?是不是让它向后看 ^(?=.*?bear grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*? 这解释了它的作用。 要修改,它取决于您要执行的操作 这
熊格里尔的插曲
。这是有道理的。但它也匹配插曲
后面跟着熊格里尔斯
的文本,例如插曲熊格里尔斯
。我在正则表达式中没有看到任何向后看的参考。最后的*?
是不是让它向后看
^(?=.*?bear grylls)(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?
这解释了它的作用。
要修改,它取决于您要执行的操作 这就是它目前所做的-
# ^(?=.*?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
我建议在格式化和创建自动注释的地方使用。所有向前看和向后看断言
(?=…)
,(?!…)
,(?)不使用文本。它不会将指针提前到当前位置,这是匹配某些文本时的正常行为
由于它不会推进索引,因此可以使用此属性检查文本的多个属性,否则,如果不向前看,很难将这些属性组合成单个表达式
在您的例子中,正则表达式检查是否存在字符串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
可以位于列表中任何字符串的前面或后面,因此需要交替检查这两种情况。干问题可以通过字符串连接来解决,但如果不可用,人们将很难进行维护
这也是密码验证中经常使用的一种技术,其中可能存在多个条件,例如至少一个字母表、至少一个数字、至少一个特殊字符、一行中没有3个相同的字符等。如果要编写一个表达式来检查上述所有属性,则会非常混乱rtion允许您在一个表达式中填充所有内容,而不会使正则表达式变得不可理解和不可维护
就我个人而言,我不太喜欢这种方法,因为将所有内容都塞进一个正则表达式是没有意义的,除非您受到工具的限制,并且不允许运行多个正则表达式。我们只需创建两个正则表达式,然后针对每个正则表达式测试字符串。性能大致相同,因为在正则表达式中完成的工作量相同事实上,我相信大多数引擎都会在上面的正则表达式中重新扫描字符串两次。我重写了原始正则表达式,这可以得到您想要的结果
^(?=.*?bear grylls).+(?=.*?(\bnbc\b|reality|episode|show|watch|series|season|premiere)).*?
它与前一个非常相似。唯一的区别是我在两个积极的前瞻性断言之间添加“+”,这将强制执行这两个部分的顺序,例如,“bear grylls插曲”将有积极的结果,而“Spice bear grylls”不会
如果没有这一点,这两个先行断言将不会有任何序列首选项。基本上,它们是完全相等的。看一看,这在您键入正则表达式时为正则表达式提供了正确的解释。这不会像您认为的那样做。^(?=.*bear grylls)
仍然匹配字符串中的任何位置。感谢NHAHDH,这澄清了关于位置的混淆。如果我理解正确,向前看比第二个选项更便宜。如果它不正确,请纠正我。@KaushalPatel:哪一个第二个选项?如果您谈论的是长正则表达式而没有向前看,那么它可能是正确的。但是如果您谈论的是如果不使用多个正则表达式,则两者应该大致相同。谢谢Sln。如何将.?*替换为。*帮助?贪婪匹配不是比懒惰匹配更昂贵吗?它便宜很多。在断言中,如果可以,请避免使用此*?
构造。