使用Bash中的正则表达式检查电子邮件地址的正确性

时间:2010-01-26 10:13:58

标签: regex bash shell email-validation

我正在尝试制作一个Bash脚本来检查电子邮件地址是否正确。

我有这个正则表达式:

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

来源:http://www.regular-expressions.info/email.html

这是我的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="test@terra.es"
if [[ $i=~$regex ]] ; then
    echo "OK"
else
    echo "not OK"
fi

脚本失败并给我输出结果:

  

10:语法错误:反引号替换中的EOF

任何线索??

8 个答案:

答案 0 :(得分:9)

这里有几个问题:

  • 需要引用正则表达式并转义特殊字符。
  • 正则表达式应该被锚定(^$)。
  • ?:不受支持,需要删除。
  • 您需要=~运营商周围的空格。

最终产品:

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="test@terra.es"
if [[ $i =~ $regex ]] ; then
    echo "OK"
else
    echo "not OK"
fi

答案 1 :(得分:7)

您无需创建如此复杂的正则表达式来检查有效的电子邮件。您可以简单地拆分“@”,然后检查是否有2个项目,一个位于@前面,另一个位于后面。

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

要进一步检查域,您可以使用dig之类的工具来查询域。它比正则表达式更好,因为@ new.jersey与正则表达式相匹配,但它实际上不是一个合适的域。

答案 2 :(得分:5)

引号,反引号等是shell脚本中的特殊字符,如果像regex一样使用它们,则需要进行转义。您可以使用反斜杠转义特殊字符,或者如果省略其中使用的单引号,则在正则表达式周围使用单引号。

我建议使用更简单的正则表达式,如.*@.*,因为所有复杂性都是徒劳的。 <{1}}看起来非常精细,任何正则表达式都会接受它,但它仍然不存在。

答案 3 :(得分:1)

Bash版本低于3.2:

if [[ "$email" =~ "^[A-Za-z0-9._%+-]+@[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._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]
then
    echo "Email address $email is valid."
else
    echo "Email address $email is invalid."
fi

{@ 3}}解释了您不应该使用非常具体的正则表达式的原因here

答案 4 :(得分:0)

您的脚本存在的问题是您需要修复引号:

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

但是,此正则表达式不接受所有语法上有效的电子邮件地址。即使它确实如此,也不是所有语法上有效的电子邮件地址都可以交付。

如果可交付地址是您关心的,那么请不要使用正则表达式或其他检查语法的方法:向用户提供的地址发送质询。 注意不要在命令调用中使用不受信任的输入!使用sendmail,运行sendmail -oi -t并将消息写入sendmail进程的标准输入,例如

To: test@terra.es.invalid
From: no-reply@your.organization.invalid
Subject: email address confirmation

To confirm your address, please visit the following link:

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

答案 5 :(得分:0)

在一次疯狂的时刻,我根据Mastering Regular Expressions书写了这个Perl子程序:

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

答案 6 :(得分:0)

我已经调整了上面的示例,使其具有一个独特的函数,该函数将使用regexp检查地址的有效性,如果域实际存在dig,否则返回错误。

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

没什么特别的。

答案 7 :(得分:0)

为聚会迟到了,但我改编了一个脚本来阅读包含电子邮件的文件,并使用RFC822正则表达式,域名拼写列表,mx查找(感谢eagle1)和不明确的电子邮件过滤来过滤它。

该脚本可以像:

一样使用
./emailCheck.sh /path/to/emailList

并生成两个文件,即筛选列表和不明确的列表。两者都已从非RFC822兼容地址,没有有效MX域的电子邮件域以及域拼写错误中清除。

脚本可以在这里找到:https://github.com/deajan/linuxscripts

欢迎更正和评论:)