2010-01-26 74 views
5

Estoy tratando de crear un script Bash para verificar si una dirección de correo electrónico es correcta.Verificación de la corrección de una dirección de correo electrónico con una expresión regular en Bash

que tienen esta expresión regular:

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

Fuente: http://www.regular-expressions.info/email.html

y este es mi escritura del golpe:

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 

El guión falla y me da este resultado:

10: Syntax error: EOF in backquote substitution

¿Alguna pista?

+0

¿Tiene usted conocimiento de los nombres de dominio internacionalizados http://www.icann.org/en/topics/idn/? ¿su expresión regular coincide con [email protected]õõ.bâr.com? – Jean

+0

Si lee ese artículo que citó exhaustivamente, verá que a) las expresiones regulares solo le ayudarán a clasificar direcciones flagrantemente ilegales, b) tendrá falsos positivos y falsos negativos, o una expresión regular completamente difícil de manejar, yc) al final, tendrá que enviar un correo electrónico a esa dirección para verificar si no solo es sintácticamente válido sino, de hecho, es correcto (lo que ninguna expresión regular puede indicarle). –

+0

echa un vistazo a esta publicación: http://solidlystated.com/scripting/proper-email-address-validation/ –

Respuesta

5

Las comillas, los "backticks" y otros son caracteres especiales en los scripts de shell y deben ser escapados si se usan como en la asignación de regex. Puede escapar de los caracteres especiales con barras diagonales inversas, o usar comillas simples alrededor de la expresión regular si omite la comilla simple utilizada en ella.

Recomendaría usar una expresión regular más simple como .*@.* porque toda la complejidad es inútil. [email protected] se ve perfectamente bien y será aceptado por cualquier expresión regular, pero aún así no existe.

6

usted tiene varios problemas aquí:

  • La expresión regular debe ser citado y caracteres especiales escapó.
  • La expresión regular debe estar anclada (^ y $).
  • ?: no es compatible y debe eliminarse.
  • Necesita espacios alrededor del operador =~.

producto final:

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

Me gustaría agregar, sin embargo, que hacer esto en bash es bastante, um, subóptimo. Pero quería destacar cómo solucionar el enfoque que había elegido. –

+0

esta expresión regular falla cuando probé en Ubuntu 13 pero pasó en Ubuntu 12 –

5

usted no tiene que crear una expresión regular tan complicada para mirar el correo válida. puede dividir en "@", luego verifique si hay 2 elementos, uno que está delante del @ y el otro al dorso.

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" 

si usted quiere hacer aún más la comprobación de dominio válido, puede utilizar herramientas como excavación para consultar el dominio. Es mejor que la expresión regular porque @ new.jersey se corresponde con la expresión regular, pero en realidad no es un dominio adecuado.

+1

Creo que este es un enfoque mucho más sensato. piense en todo el sitio web que no permite: [email protected], aunque este es un correo electrónico perfectamente válido. debería deshacerse de la mayoría de las falsificaciones y aún estar bien. podrías hacerlo un poco más fuerte al verificar la presencia de un '.' en el segundo elemento y asegurándose de que separa el segundo elemento en 2 subelementos.Piense en dominios internacionales, por ejemplo, – Jean

+0

@Jean: el segundo elemento también puede contener más de dos subcadenas separadas por un punto, por lo que está bien, aunque podría querer enviar correos electrónicos como 'usuario @ localhost' y en algunos casos – rubo77

0

El problema inmediato con su guión es que debe arreglar la cita:

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])?' 

Sin embargo, esta expresión regular no acepta todas las direcciones de correo electrónico sintácticamente válidos. Incluso si lo hiciera, no todas las direcciones de correo electrónico sintácticamente válidas serán entregadas.

Si las direcciones entregables son lo que le importa, entonces no se moleste con una expresión regular u otra forma de verificar la sintaxis: envíe un desafío a la dirección que el usuario proporciona. ¡Tenga cuidado de no utilizar datos no confiables como parte de una invocación de comando! Con sendmail, ejecute sendmail -oi -t y escriba un mensaje en la entrada estándar del proceso de sendmail, , p.,

To: [email protected] 
From: [email protected].organization.invalid 
Subject: email address confirmation 

To confirm your address, please visit the following link: 

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

versión Bash menos de 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 

Las razones por las que no debe usar una expresión regular muy específico, al igual que usted tiene, se explican here.

+0

este fallará para [email protected] usando bash shell –

+0

En la versión 3.2 de bash cambiaron la forma en que funcionan las expresiones regulares. Para mantenerlo corto, no desea las comillas en la parte de expresión regular de la condición. Para su referencia http://stackoverflow.com/questions/218156/bash-regex-with-quotes – rouble

0

En un momento de locura una vez, me escribió esta subrutina Perl basado en el dominio de las expresiones libro regular:

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

He ajustado los ejemplos anteriores para tener una función única que verificará la validez de la dirección con la expresión regular y si el dominio real existe con dig, de lo contrario devuelve un error.

#!/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 

Nada especial.

0

Llegué tarde a la fiesta, pero adapté un script para leer un archivo que contenía correos electrónicos y filtrarlo usando RFC822 regex, listas de errores de dominio, búsqueda mx (gracias a eagle1 aquí) y ambiguo filtrado de correo electrónico.

La secuencia de comandos se puede utilizar como:

./emailCheck.sh /path/to/emailList 

y produce dos archivos, la lista filtrada y la lista ambigua. Ambos ya han sido eliminados de direcciones que no son compatibles con RFC822, dominios de correo electrónico que no tienen dominios MX válidos y errores tipográficos de dominio.

de secuencias de comandos se puede encontrar aquí: https://github.com/deajan/linuxscripts

correcciones y comentarios son bienvenidos :)

Cuestiones relacionadas