2012-10-26 61 views
5

我有一個很好的電子郵件vaidation從正則表達式: Email regular expression任何人都可以告訴我爲什麼這個C#電子郵件驗證正則表達式(正則表達式)掛起?

public static void Main(string[] args) 
    { 
     string value = @"cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc"; 
     var regex = new Regex(
      @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", 
      RegexOptions.Compiled); 
     var x = regex.Match(value); // Hangs here !?! 
     return; 
    } 

它工作在大多數情況下,但上面掛起的代碼,燃燒100%的CPU ......我在W8 Metro應用測試過。和一個標準的.Net 4.5應用程序。

誰能告訴我爲什麼會發生這種情況,如果有一個好的電子郵件驗證REGEX沒有掛起,或者是否有辦法解決這個問題?

非常感謝, 喬恩

+1

[這](http://www.regular-expressions.info/catastrophic.html)可以幫助你找出它爲什麼會掛起。[This](http://www.regular-expressions.info/email.html)可能會幫助您找出如何正確匹配電子郵件地址與正則表達式。 –

+0

你應該閱讀此爲了創建一個正確的電子郵件匹配正則表達式http://www.regular-expressions.info/email.html – CaffGeek

回答

14

它解釋爲什麼它掛起:Catastrophic backtracking

讓我們簡化了正則表達式的關鍵部分:

(\w*[0-9a-zA-Z])*@ 

你有

  • 的可選部分\w*可以匹配相同的字符,如下面的部分[0-9a-zA-Z],所以兩者合用翻譯,本質上爲\w+
  • 嵌套量詞:(\w+)*

這意味着,給定s = "cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc",正則表達式的這一部分需要在非匹配決定當未發現以下@之前檢查的s所有可能的排列(其數目在2**(len(s)-1))。

既然你不能有任何的正則表達式驗證電子郵件地址(有太多的極端案例在規範中),它通常最好

  • 我們做一個最小的正則表達式檢查(^.*@.*$
  • 使用解析器來檢查有效性(如@ Fake.It.Til.U.Make.It建議)
  • 嘗試併發送電子郵件給它 - 即使看似有效的地址可能是假的,所以你必須做無論如何。

只是爲了保持完整性,您可以避免atomic groups幫助回溯問題:

var regex = new Regex(
    @"^([0-9a-zA-Z](?>[-.\w]*[0-9a-zA-Z])*@(?>[0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", 
    RegexOptions.Compiled); 
+1

優秀的分析 – Anirudha

+0

嗨,謝謝你的詳細答案:-)我將使用像「做一個最小正則表達式檢查(^。* @。* $)」這樣的驗證,因爲我們真的只是試圖幫助用戶避免輸入錯誤'..'。如果他們輸入了錯誤的地址,這不是世界末日,因爲我們有其他電子郵件恢復機制。乾杯,喬恩 –

4

永遠不要regex驗證電子郵件..

您可以使用MailAddress類驗證它

try 
{ 
    address = new MailAddress(address).Address; 
    //address is valid 
} 
catch(FormatException) 
{ 
    //address is invalid 
} 
+0

嗨,我喜歡這種方法,但不幸的是'System.Net.Mail.MailAddress'isn 'Win8 C#'/ WinRT無法使用。你知道可用的替代方案嗎?它也不回答*爲什麼*上述正則表達式掛起。謝謝你,Jon –

+0

@JonRea在你正則表達式中你使用'[]''中的'-',它需要像這樣轉義:'\ -' – Anirudha

+1

@ Fake.It.Til.U.Make.It:不,' - '只需要在角色類中逃脫,如果它不是第一個或最後一個字符。 –

0

想這是因爲[ - 。\ w]正則表達式,請嘗試使用:

^[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*@(?:(\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$ 

此外,在.net 4.5 EmailAttribute應該可用,不知道雖然

+0

'正規表達式'是不好的電子郵件驗證..一個真正的電子郵件ID的正則表達式會遠遠遠大於這個... – Anirudha

+0

它只取決於就如何看到正確的電子郵件。 MailAddress類也可以使用正則表達式來進行電子郵件驗證 - 反映它:)。此外,電子郵件可能是國家特定的,所以正則表達式是一種方式去我 – Sergio

+0

那一個「災難性回溯」:-) - 我得到相同的掛起... –

相關問題