2012-10-26 21 views
5

tôi nhận được một email vaidation regex tốt từ: Email regular expressionBất cứ ai có thể cho tôi biết lý do tại sao C# email xác nhận biểu thức chính quy (regex) bị treo?

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; 
    } 

Nó hoạt động trong hầu hết các trường hợp, nhưng các mã trên treo, cháy 100% CPU ... Tôi đã được thử nghiệm trong một W8 metro App. và trên một ứng dụng tiêu chuẩn .Net 4.5.

Bất cứ ai có thể cho tôi biết lý do tại sao điều này xảy ra và nếu có REGEX xác thực email tốt không treo, hoặc nếu có cách sửa lỗi này?

Rất cám ơn, Jon

+1

[này] (http://www.regular-expressions.info/catastrophic.html) có thể giúp bạn tìm hiểu lý do tại sao nó bị treo.[This] (http://www.regular-expressions.info/email.html) có thể giúp bạn tìm hiểu cách đối sánh địa chỉ email đúng cách với regex. –

+0

Bạn nên đọc điều này để tạo một email phù hợp với regex http://www.regular-expressions.info/email.html – CaffGeek

Trả lời

14

Giải thích tại sao nó bị treo: Catastrophic backtracking.

Hãy đơn giản hóa các phần quan trọng của regex:

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

Bạn có

  • một phần \w* có thể phù hợp với nhân vật tương tự như phần sau [0-9a-zA-Z], vì vậy hai kết hợp dịch không bắt buộc, về bản chất, để \w+
  • định lượng lồng nhau: (\w+)*

Điều này có nghĩa rằng, cho s = "cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc", phần này của regex cần phải rà soát tất cả các hoán vị có thể của s (mà số tại 2**(len(s)-1)) trước khi quyết định một tổ chức phi trận đấu khi @ Sau đây là không tìm thấy.

Vì bạn không thể xác nhận một địa chỉ e-mail với bất kỳ regex (có quá nhiều trường hợp góc trong spec), nó thường là tốt nhất để

  • làm một kiểm tra regex tối thiểu (^.*@.*$)
  • sử dụng trình phân tích cú pháp để kiểm tra tính hợp lệ (như @ Fake.It.Til.U.Make.It đã đề xuất)
  • thử và gửi e-mail đến nó - ngay cả địa chỉ có vẻ hợp lệ có thể không có thật, vì vậy bạn phải làm điều này anyway.

Chỉ cần cho đầy đủ, bạn có thể tránh các vấn đề quay lui với sự giúp đỡ của 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

phân tích tuyệt vời – Anirudha

+0

Xin chào, Cảm ơn câu trả lời chi tiết :-) Tôi sẽ đi với một xác nhận như "làm một kiểm tra regex tối thiểu (^. * @. * $)" - được như chúng tôi đang thực sự chỉ cố gắng để giúp người dùng tránh lỗi chính tả như gõ ví dụ '..'. Nếu họ nhập sai địa chỉ, thì đó không phải là kết thúc của thế giới khi chúng tôi có các cơ chế khôi phục email khác. Chúc mừng, Jon –

4

Đừng bao giờ sử dụng regex để xác nhận email ..

Bạn có thể sử dụng MailAddress lớp để xác nhận nó

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

Xin chào, tôi thích cách tiếp cận đó, nhưng tiếc là 'System.Net.Mail.MailAddress' isn không có trong 'Win8 C#'/WinRT. Bạn có biết một giải pháp thay thế có sẵn không? Nó cũng không trả lời * tại sao * regex trên bị treo. Cảm ơn, Jon –

+0

@JonRea trong bạn regex ur bằng cách sử dụng '-' trong' [] 'mà cần phải được thoát như thế này:' \ -' – Anirudha

+1

@ Fake.It.Til.U.Make.It: Không, các '- 'chỉ cần được thoát trong một lớp nhân vật nếu nó không phải là ký tự đầu tiên hoặc cuối cùng. –

0

đoán đó là vì [-. \ w] trong regex, hãy thử sử dụng điều này:

^[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})(\]?)$ 

Ngoài ra, trong .net 4.5 EmailAttribute nên có sẵn, không chắc chắn mặc dù

+0

'regex' không tốt cho xác nhận email .. thực tế regex cho id email sẽ là xa, xa, lớn hơn rất nhiều ... – Anirudha

+0

Nó chỉ phụ thuộc về cách bạn thấy email chính xác. Lớp MailAddress có thể sử dụng regex để xác nhận email quá - phản ánh nó :). Ngoài ra email có thể là quốc gia cụ thể, vì vậy regex là một cách để đi cho tôi – Sergio

+0

Đó là một "trào ngược thảm khốc" quá :-) - Tôi nhận được cùng hang ... –

Các vấn đề liên quan