[英]Why Regex IsMatch() hangs
我有一個exressression來驗證電子郵件地址:
string REGEX_EMAIL = @"^\w+([\.\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\¦\}\~]*\w+)*@\w+([\.\-]\w+)*\.\w+([\.\-]\w+)*$";
如果地址正確,IsMatch()方法會快速顯示真實結果。 但是如果地址字符串很長且錯誤,則此方法會掛起。
我該怎么做才能提高這種方法的速度?
謝謝。
您正在經歷災難性的回溯 。
簡化的正則表達式:
Regex regexObj = new Regex(@"^\w+([-.!#$%&'*+/=?^`{¦}~]*\w+)*@\w+([.-]\w+)*\.\w+([.-]\w+)*$");
有潛在的問題,例如([.-]\\w+)*\\.
如果.
例如,缺少一個很長的字符串然后必須考慮所有可能的組合,以便你的正則表達式找出它實際上失敗了。
你有幾件事正在影響這個正則表達式的表現。
你可以通過在幾個關鍵位置使用+
而不是*
來提高性能,但這當然會改變正則表達式將匹配和不匹配的內容。 因此,我發現的最簡單的修復實際上涵蓋在上面的災難性回溯文章中。 在這種情況下,您可以使用nonbacktracking子表達式來顯着提高性能,而無需以任何重要的方式更改正則表達式的行為。
nonbacktracking子表達式看起來像這樣...... (?>pattern)
所以試試這個正則表達式:
^\w+(?>[\.\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\¦\}\~]*\w+)*@\w+([\.\-]\w+)*\.\w+([\.\-]\w+)*$
在一個稍微相關的主題上,我檢查有效電子郵件地址的理念有點不同。 例如,像你這樣的長正則表達式可能會出現性能問題。
其次,電子郵件地址國際化即將到來,這使得所有這些更加復雜化。
最后,任何基於正則表達式的電子郵件驗證的主要目的是捕獲拼寫錯誤並公然嘗試通過您的表單而不輸入真實的電子郵件地址。 但要檢查電子郵件地址是否為正版,則需要您向該地址發送電子郵件。
所以我的理念是錯誤接受太多。 事實上,這是一件非常簡單的事情......
^.+@.+\..+$
這應該匹配任何可以想象的有效電子郵件地址,以及一些無效的電子郵件地址。
所以,有一些回溯問題。 您可以通過謹慎使用獨立子表達式構造來減少這些問題,但是您仍然會遇到問題,因為內部表達式不具有該約束。 最好的辦法是分開主要部分。
將其更改為有助於(擴展):
^
(?>
\w+
(
[\.\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\¦\}\~]*
\w+
)*
@
\w+
)
(?>
([\.\-]\w+)*
\.
\w+
([\.\-]\w+)*
)
$
但是,如果通過放置一些放置好的斷言來重構等效表達式,然后重新添加獨立的子表達式分組,則可以實際上消除回溯。 通過我的正則表達式dubugger運行它表明它只需要很少的步驟來傳遞或失敗(擴展):
^
(?>
\w+
[\.\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\¦\}\~\w]*
(?<=\w)
@
\w+
)
(?=.*\.\w)
(?>
([\.\-]\w+)+
)
$
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.