2012-10-26 12 views
5

Dostałem dobrą email vaidation regex od: Email regular expressionCzy ktoś może mi powiedzieć, dlaczego to wyrażenie regularne sprawdzania poprawności wiadomości e-mail C# (regex) zawiesza się?

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

to działa w większości przypadków, ale powyższy kod zawiesza, palenie 100% CPU ... Przetestowałem w W8 metra App. oraz w standardowej aplikacji .Net 4.5.

Czy ktoś może mi powiedzieć, dlaczego tak się dzieje, i czy istnieje dobry REGEX sprawdzania poprawności wiadomości e-mail, który się nie zawiesza, lub czy istnieje sposób, aby to naprawić?

Dziękujemy, Jon

+1

[To] (http://www.regular-expressions.info/catastrophic.html) może ci pomóc dowiedzieć się, dlaczego wisi.[This] (http://www.regular-expressions.info/email.html) może pomóc ci dowiedzieć się, jak poprawnie dopasować adresy e-mail do regex. –

+0

Powinieneś przeczytać to, aby utworzyć prawidłowy adres e-mail zgodny z wyrażeniem regularnym http://www.regular-expressions.info/email.html – CaffGeek

Odpowiedz

14

Wyjaśnienie, dlaczego wisi: Catastrophic backtracking.

Załóżmy uprościć zasadniczą część regex:

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

Masz

  • opcjonalną część \w*, które można dopasować te same znaki jak w dalszej części [0-9a-zA-Z], więc dwa połączone tłumaczyć, w istocie, do \w+
  • zagnieżdżone kwantyfikatory: (\w+)*

Oznacza to, że ze względu s = "cvcvcvcvvcvvcvcvcvcvcvvcvcvcvcvcvvccvcvcvc", ta część regex musi sprawdzić wszystkie możliwe permutacje s (których liczba na 2**(len(s)-1)) przed podjęciem decyzji o braku meczu, gdy po @ nie znaleziono.

Ponieważ nie można sprawdzić poprawność adresu e-mail z dowolnego regex (jest ich zbyt wiele przypadków narożne w ciemno), to zazwyczaj najlepiej

  • zrobić minimalną kontrolę regex (^.*@.*$)
  • użyj parsera do sprawdzenia poprawności (np. @ Fake.It.Til.U.Make.It suggested)
  • spróbuj i wyślij do niego e-mail - nawet pozornie poprawny adres może być fałszywy, więc musisz zrobić i tak.

Tylko dla kompletności, ty może uniknąć problemów Backtracking z pomocą 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

doskonała analiza – Anirudha

+0

Witam, dziękuję za szczegółową odpowiedź :-) Pójdę z sprawdzaniem poprawności, jak "wykonaj minimalne sprawdzanie regex (^. * @. * $)" - ponieważ tak naprawdę staramy się tylko pomóc użytkownikowi uniknąć literówek takich jak pisanie np. "..". Jeśli wprowadzą zły adres, to nie koniec świata, ponieważ mamy inne mechanizmy odzyskiwania poczty. Pozdrawiam, Jon –

4

Nigdy nie używać regex do sprawdzania e-mail ..

Można użyć MailAddress klasę, aby potwierdzić to

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

Witam, podoba mi się to podejście, ale niestety "System.Net.Mail.MailAddress" nie jest dostępne w Win8 C#/WinRT. Czy znasz alternatywę, która jest dostępna? Nie odpowiada także * dlaczego * powyższe wyrażenie zwisa. Dzięki, Jon –

+0

@ JonRea w tobie wyślij ponownie za pomocą '-' w' [] ', które muszą zostać usunięte w ten sposób:' \ -' – Anirudha

+1

@ Fake.It.Til.U.Make.It: Nie, '- 'only musi być escaped w klasie postaci, jeśli nie jest to pierwszy lub ostatni znak. –

0

domyślić, że to z powodu [-. \ w] w regex, spróbuj uż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})(\]?)$ 

Również w .net 4.5 EmailAttribute powinny być dostępne, nie wiesz jednak,

+0

'regex' nie jest dobre dla sprawdzania poprawności poczty e-mail .. rzeczywiste wyrażenie na adres e-mail id byłoby daleko, daleko, znacznie większe niż to ... – Anirudha

+0

To tylko zależy o tym, jak widzisz prawidłowy e-mail. Klasa MailAddress może również używać wyrażenia regularnego do sprawdzania poprawności poczty e-mail - odzwierciedla to :). Również e-mail może być specyficzny dla kraju, więc regex to sposób, aby przejść do mnie – Sergio

+0

To jedno "Catastrophicly backtracks" zbyt :-) - Tak samo mi się powodzi ... –

Powiązane problemy