8

我正在尝试制作一个 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

有什么线索吗??

4

8 回答 8

13

你在这里有几个问题:

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

完成品:

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
于 2010-01-26T10:45:17.283 回答
10

您不必创建如此复杂的正则表达式来检查有效的电子邮件。您可以简单地在“@”上拆分,然后检查是否有 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 与正则表达式匹配,但它实际上不是一个合适的域。

于 2010-01-26T10:46:07.127 回答
5

引号、反引号和其他字符是 shell 脚本中的特殊字符,如果像在regex. 您可以使用反斜杠转义特殊字符,或者如果您省略其中使用的单引号,则在正则表达式周围使用单引号。

我建议使用更简单的正则表达式,.*@.*因为所有的复杂性都是徒劳的。foo@example.com看起来非常好,可以被任何正则表达式接受,但它仍然不存在。

于 2010-01-26T10:16:53.657 回答
1

低于 3.2 的 Bash 版本:

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.2 的 Bash 版本

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

此处解释了您不应该使用非常具体的正则表达式的原因,就像您所拥有的那样。

于 2011-04-19T16:25:09.690 回答
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 进程的标准输入,例如

致:test@terra.es.invalid
来自:no-reply@your.organization.invalid
主题:电子邮件地址确认

要确认您的地址,请访问以下链接:

http://www.your.organization.invalid/verify/1a456fadef213443
于 2010-01-26T14:33:47.743 回答
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});
于 2011-04-19T16:53:35.927 回答
0

我已经调整了上面的示例,使其具有一个独特的函数,该函数将使用正则表达式检查地址的有效性,以及是否使用 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

没什么特别的。

于 2014-03-27T13:56:56.647 回答
0

聚会迟到了,但我修改了一个脚本来读取包含电子邮件的文件,并使用 RFC822 正则表达式、域错字列表、mx 查找(感谢 eagle1 此处)和模棱两可的电子邮件过滤对其进行过滤。

该脚本可以像这样使用:

./emailCheck.sh /path/to/emailList

并生成两个文件,过滤列表和模糊列表。两者都已从不符合 RFC822 的地址、没有有效 MX 域的电子邮件域和域拼写错误中清除。

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

欢迎指正和评论:)

于 2016-03-30T10:42:46.427 回答