3 回答

TA貢獻1851條經驗 獲得超5個贊
這會災難性地回溯在最后一個結束</tag:main>
標記之后出現的長序列空間??紤]主題字符串以100個空格結尾的情況。首先,它將它們全部與.
交替的左側相匹配。這失敗了,因為沒有結束標記,所以它嘗試匹配最后一個字符\s
。這也失敗了,所以它嘗試匹配倒數第二個空格作為a \s
和最后一個空格作為a .
。失敗(仍然沒有結束標記)所以它嘗試最后一個空格作為\s
。當失敗時它將第三個到最后一個空格匹配為a \s
并嘗試所有4種方式來匹配最后兩個空格。當失敗時,它會嘗試倒數第四個空格\s
以及最后3個空格中的所有8種方式。然后是16,32等。宇宙在它到達第100個到最后的空間之前結束。
由于災難性的回溯,不同的VM對regexp匹配的反應不同。有些人只會報告“不匹配”。在V8中,它就像編寫任何其他無限或近無限循環一樣。
使用非貪婪*
會做你想要的(你想要在第一個</tag:main>
而不是最后一個停止),但仍會對缺少關閉序列的長串空間進行災難性的回溯。
確保內括號中的相同字符不能與交替的兩側匹配將減少從指數一到一的問題,該問題在字符串的長度上是線性的。使用字符類而不是替換或放在\n
交替欄的右側。 如果您按下一長串空格,則正則表達式引擎在終止之前不會嘗試所有左右 - 左等組合\n
,.
因此是不相交的。

TA貢獻1862條經驗 獲得超6個贊
我認為這是災難性的追溯。
我認為問題的一部分可能是dot和\ s不是互斥的。
如果我改變你的表達方式
<tag:main>((?:.|[\r\n])*)</tag:main>
并在Regex Buddy調試器中運行它,如果測試字符串不匹配,它會更快地失敗。
添加回答
舉報