2010-01-26 17 views
5

Próbuję utworzyć skrypt Bash, aby sprawdzić, czy adres e-mail jest poprawny.Sprawdzanie poprawności adresu e-mail z wyrażeniem regularnym w Bash

Mam tego wyrażenia regularnego:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])? 

Źródło: http://www.regular-expressions.info/email.html

I to jest mój skrypt bash:

regex=[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])? 

i="[email protected]" 
if [[ $i=~$regex ]] ; then 
    echo "OK" 
else 
    echo "not OK" 
fi 

Skrypt nie powiedzie się i dać mi ten wynik:

10: Syntax error: EOF in backquote substitution

Jakaś wskazówka ??

+0

Czy jesteś świadomy umiędzynarodowionych domen http://www.icann.org/en/topics/idn/? czy twoje wyrażenie regularne pasuje [email protected]õõ.bâr.com? – Jean

+0

Jeśli przeczytasz dokładnie ten artykuł, zobaczysz, że a) wyrazy regularne pomogą tylko uporządkować rażąco nielegalne adresy, b) będziesz mieć albo fałszywe alarmy i fałszywe negatywy, albo zupełnie nieporęczne wyrażenie, c) na końcu będziesz musiał wysłać wiadomość e-mail na ten adres, aby sprawdzić, czy jest ona nie tylko poprawna pod względem składni, ale w rzeczywistości poprawna (której regex nie może ci powiedzieć). –

+0

sprawdź ten wpis: http://solidlystated.com/scripting/proper-email-address-validation/ –

Odpowiedz

5

Cytaty, krzyżyki i inne są znakami specjalnymi w skryptach powłoki i należy je zamykać, jeśli są używane tak, jak w zadaniu regex. Możesz uciec od znaków specjalnych z ukośnikami odwrotnymi lub użyć pojedynczego cudzysłowu wokół wyrażenia regularnego, jeśli pominiesz pojedynczy cytat użyty w nim.

Polecam użyć prostszego wyrażenia regularnego, takiego jak .*@.*, ponieważ cała złożoność jest daremna. [email protected] wygląda doskonale i będzie akceptowany przez dowolne wyrażenie regularne, ale nadal nie istnieje.

6

Masz kilka problemów tutaj:

  • Wyrażenie regularne musi być cytowane i znaki specjalne uciekł.
  • Wyrażenie regularne powinno być zakotwiczone (^ i $).
  • ?: nie jest obsługiwany i musi zostać usunięty.
  • Potrzebujesz miejsca wokół operatora =~.

produkt końcowy:

regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$" 

i="[email protected]" 
if [[ $i =~ $regex ]] ; then 
    echo "OK" 
else 
    echo "not OK" 
fi 
+0

Chciałbym jednak dodać, że robienie tego w bash jest całkiem, um, nieoptymalne. Ale chciałem podkreślić, jak poprawić podejście, które wybrałeś. –

+0

to wyrażenie kończy się niepowodzeniem, gdy testowałem w Ubuntu 13, ale przeszło w Ubuntu 12 –

5

nie trzeba do stworzenia takiego skomplikowanego wyrażenia regularnego, aby sprawdzić adres email. możesz podzielić na "@", a następnie sprawdzić, czy są 2 przedmioty, jeden przed @, a drugi z tyłu.

i="[email protected]" 
IFS="@" 
set -- $i 
if [ "${#@}" -ne 2 ];then 
    echo "invalid email" 
fi 
domain="$2" 
dig $domain | grep "ANSWER: 1" 1>/dev/null && echo "domain ok" 

Jeśli chcesz zrobić dalsze sprawdzenie poprawnej domeny, możesz użyć narzędzi takich jak dig, aby wysłać zapytanie do domeny. Jest lepszy niż regex, ponieważ @ new.jersey jest dopasowywany przez regex, ale w rzeczywistości nie jest właściwą domeną.

+1

Uważam, że jest to znacznie bardziej uciążliwe podejście. pomyśl o wszystkich stronach, które uniemożliwiają: [email protected], mimo że jest to całkowicie poprawny adres e-mail. powinien pozbyć się większości podróbek i nadal być w porządku. możesz zrobić to nieco mocniej, sprawdzając obecność "." w drugim elemencie i upewniając się, że oddziela drugi element w 2 podelementach.Pomyśl o domenach międzynarodowych na przykład – Jean

+0

@Jean: drugi element może również zawierać więcej niż dwa podciągi oddzielone kropką, więc to jest w porządku, chociaż możesz chcieć zezwolić na wiadomości mailowe 'user @ localhost', a także w niektórych przypadkach – rubo77

0

Bezpośrednim problem ze skryptu jest trzeba naprawić przytoczyć:

regex='[a-z0-9!#$%&'"'"'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'"'"'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?' 

Jednak to wyrażenie regularne nie akceptuje wszystkie składniowo poprawne adresy e-mail. Nawet jeśli tak się stało, nie wszystkie poprawne syntaktycznie adresy e-mail są możliwe do dostarczenia.

Jeśli ważne są dostarczane adresy, nie przejmuj się wyrażeniem regularnym lub innymi metodami sprawdzania składni: wyślij wyzwanie na adres podany przez użytkownika. Należy uważać, aby nie używać niezaufanych danych wejściowych jako części wywołania polecenia! Korzystając z sendmaila, uruchom sendmail -oi -t i napisz wiadomość na standardowe wejście procesu sendmail, np. , np.,

To: [email protected] 
From: [email protected] 
Subject: email address confirmation 

To confirm your address, please visit the following link: 

http://www.your.organization.invalid/verify/1a456fadef213443 
1

wersja Bash mniej niż 3.2:

if [[ "$email" =~ "^[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,4}$" ]] 
then 
    echo "Email address $email is valid." 
else 
    echo "Email address $email is invalid." 
fi 

Bash version greater than or equal to 3.2:

if [[ "$email" =~ ^[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]] 
then 
    echo "Email address $email is valid." 
else 
    echo "Email address $email is invalid." 
fi 

powodów, dla których nie powinno się używać bardzo specyficzny regex, jak trzeba, wyjaśnione here.

+0

zakończy się niepowodzeniem na adres [email protected] przy użyciu powłoki bash –

+0

W wersji 3.2 bash zmienili działanie regexs. Aby było krótko, nie chcesz cytować części regex warunku. Dla Twojej wygody http://stackoverflow.com/questions/218156/bash-regex-with-quotes – rouble

0

W chwili szaleństwa Kiedyś napisałem ten podprogram Perl w oparciu o Wyrażenia regularne książki:

sub getRFC822AddressSpec 
{ 
    my ($esc, $space, $tab, $period) = ('\\\\', '\040', '\t', '\.'); 
    my ($lBr, $rBr, $lPa, $rPa)  = ('\[', '\]', '\(', '\)'); 
    my ($nonAscii, $ctrl, $CRlist) = ('\200-\377', '\000-\037', '\n\015'); 

    my $qtext  = qq{ [^$esc$nonAscii$CRlist] }; # within "..." 
    my $dtext  = qq{ [^$esc$nonAscii$CRlist$lBr$rBr] }; # within [...] 
    my $ctext  = qq{ [^$esc$nonAscii$CRlist()] }; # within (...) 
    my $quoted_pair = qq{ $esc [^$nonAscii] }; # an escaped char 
    my $atom_char = qq{ [^()$space<>\@,;:".$esc$lBr$rBr$ctrl$nonAscii] }; 
    my $atom  = qq{ $atom_char+  # some atom chars 
          (?!$atom_char) # NOT followed by part of an atom 
         }; 
    # rfc822 comments are (enclosed (in parentheses) like this) 
    my $cNested  = qq{ $lPa (?: $ctext | $quoted_pair)* $rPa }; 
    my $comment  = qq{ $lPa (?: $ctext | $quoted_pair | $cNested)* $rPa }; 

    # whitespace and comments may be scattered liberally 
    my $X   = qq{ (?: [$space$tab] | $comment)* }; 

    my $quoted_str = qq{ " (?: $qtext | $quoted_pair)* " }; 
    my $word  = qq{ (?: $atom | $quoted_str) }; 
    my $domain_ref = $atom; 
    my $domain_lit = qq{ $lBr (?: $dtext | $quoted_pair)* $rBr }; 
    my $sub_domain = qq{ (?: $domain_ref | $domain_lit) }; 
    my $domain  = qq{ $sub_domain (?: $X $period $X $sub_domain)* }; 
    my $local_part = qq{ $word (?: $X $period $X $word)* }; 
    my $addr_spec = qq{ $local_part $X \@ $X $domain }; 

    # return a regular expression object 
    return qr{$addr_spec}ox; 
} 

my $spec = getRFC822AddressSpec(); 
my $address = q{foo (Mr. John Foo) @ bar. example}; 
print "$address is an email address" if ($address =~ qr{$spec}); 
0

Mam skorygowanej powyższe przykłady mają unikalną funkcję, która sprawdza ważność adres z wyrażeniem regularnym i jeśli domena rzeczywiście istnieje z wykopem, w przeciwnym razie zwróci błąd.

#!/bin/bash 
#Regexp 
regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$" 

#Vars 
checkdig=0; 
checkreg=0; 
address=$1; 
maildomain=`echo $address | awk 'BEGIN { FS = "@" } ; { print $2 }'`; 

#Domain Check 
checkdns() { 
     echo $maildomain | awk 'BEGIN { FS = "@" } ; { print $2 }' | xargs dig $maildomain | grep "ANSWER: 0" 1>/dev/null || checkdig=1; 
} 

#Regexp 
checkreg() { 
     if [[ $address =~ $regex ]] ; 
       then checkreg=1; 
     fi 
} 

#Execute 
checkreg; 
checkdns; 

#Results 
if [ $checkreg == 1 ] && [ $checkdig == 1 ]; 
     then echo "OK"; 
     else echo "not OK"; 
fi 
#End 

Nic specjalnego.

0

Zbyt późno na imprezę, ale dostosowałem skrypt do czytania pliku zawierającego e-maile i filtrowania go za pomocą regex RFC822, listy liter domen, wyszukiwania mx (dzięki eagle1 tutaj) i niejednoznaczne filtrowanie wiadomości e-mail.

Skrypt może być używany jak:

./emailCheck.sh /path/to/emailList 

i tworzy dwa pliki, listę filtrowaną i listę niejednoznaczne. Oba są już usunięte z adresów niezgodnych z RFC822, domen e-mail, które nie mają prawidłowych domen MX i literówek domen.

Script można znaleźć tutaj: https://github.com/deajan/linuxscripts

poprawki i komentarze są mile widziane :)

Powiązane problemy