2014-10-09 112 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