2016-09-15 35 views
2

我有一個和/或正則表達式即(PatternA | PatternB),其中我只在PatternB不存在時才採用PatternA(PatternB總是在PatternA之後出現,但更重要)所以我在PatternA Pipe中放置了一個負向前視。爲什麼Negative Lookahead超時和/或Pipe

這適用於較短的文本塊:

https://regex101.com/r/bU6cU6/5

但在較長的文本塊超時:

https://regex101.com/r/bU6cU6/2

我不明白的是,如果我把PatternA與Neg在同一長文本塊中獨自前行,只需32步即可拒絕它:

https://regex101.com/r/bU6cU6/3

,如果我在同樣長的文本塊把PatternB單獨只需要18個步驟來接受它:

https://regex101.com/r/bU6cU6/4

所以我不知道爲什麼它正在採取100,000以上/超時首先拒絕(32步),然後用管子接受(18步)。是否有另一種/更好的方法來構建,因此它首先檢查PatternA,而不是PatternB,因爲現在它正在做一些我不明白從50步到100k +的事情。

+0

在文檔中的每個位置執行前瞻。這是非常低效的。您可以在'Option1:'text:'Option1:(?!。* Option2)\ *。*?(?P Bob | David | Ted | Alice)| \ * Option2(?P Juan) –

+0

@WiktorStribiżew這是有道理的。在前面的問題http://stackoverflow.com/questions/39482021/fixing-negative-assertion-for-end-of-string我被告知把它放在字符串的開頭,並接受了答案,並繼續前進。如果事實上不是正確的方式,也許我應該不接受,因爲看起來並不正確。上述和接受的答案在這裏都很好地解決了這個問題。 – user3649739

回答

1

與「全局」正則表達式(匹配多個匹配項)一起使用的未錨定周邊引起的操作太多,效率低下。它們應該被「錨定」到某個具體的環境中。通常,它們在字符串的開始處(向前)或向後(向後)移動。

對於你的情況,你可以通過在Option1:之後放置它來「錨定」它,以確保它僅在Option1:被匹配後才被執行。

Option1:(?!.*Option2)\*.*?(?P<Capture>Bob|David|Ted|Alice)|\*Option2 (?P<Capture2>Juan) 
     ^^^^^^^^^^^^^ 

this regex demo

一些更多的答案:

我不明白的是,如果我把PatternA與負片向前看獨自一人在同樣長的文本塊只需要32步驟來拒絕它

是的,但你測試它與內部優化ON。禁用它們,你會看到

enter image description here

,如果我在同樣長的文本塊,只需要18個步驟來接受它把PatternB獨自:

像預期的那樣找到匹配,在一個非常有效的方式:

enter image description here

+0

好的,我應該在提交之前查看你的答案。我要離開我的,但@user,請接受這個。 –

1

你的主要問題是上廁所的位置kahead。前瞻必須在每個位置進行嘗試,並且每次都必須掃描剩餘的所有字符。較長的測試字符串長度超過3500個字符;這加起來。

如果你的正則表達式沒有錨定,你應該總是試着用一些具體的東西來啓動它,這些東西會失敗或者很快成功 - 文字是最好的。在這種情況下,顯然您可以將後視圖移回:Option1:\*(?!.*Option2)而不是(?!.*Option2)Option1:\*。 (注意前面缺少尾部.*;你不需要那個。)

但是當你單獨匹配時,爲什麼PatternA快得多?內部優化。當正則表達式只是(?!.*Option2.*)Option1:\*.*?(?P<Capture>(Bob|David|Ted|Alice))時,正則表達式引擎可以知道匹配必須以Option1:*開頭,所以它直接進入該位置進行首次匹配嘗試。較長的正則表達式太複雜,並且不會發生優化。

你可以在Regex101上使用「regex debugger」選項來測試,然後檢查DISABLE INTERNAL ENGINE OPTIMIZATIONS。步數可以回到超過100,000。

相關問題