分隔符电子邮件地址的正则表达式

19
我正在寻找一个正则表达式来验证以下电子邮件地址列表: test1@abd.com;test.test@abc.com;test3@test.comtest1@abd.com;test.test@abc.com;test3@test.com; 列表末尾有可选的";"。
谢谢,

我希望有一个好的答案来解决这个问题。 - dsdsdsdsd
有一个好的答案:不要把正则表达式用于所有事情。 - miken32
6个回答

25

更新

不要拆分分隔符并分别验证每个部分。我建议设置匹配超时和/或非回溯标志,以防止匹配时过度使用CPU。


原始回答

来自:http://regexlib.com/RETester.aspx?regexp_id=1007

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+([;.](([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$

1
整个表达式没有正确发布。正确的表达式在帖子中链接的网站上。 - Evan Mulawski
1
Evan:iPad不能让你在一行开头插入四个空格吗?我现在看到iPad无法处理反引号,但是所有其他的SO标记都可以手动输入。而且似乎有一些解决反引号问题的方法:http://meta.stackoverflow.com/search?q=iPad - Alan Moore
-1 .... 当我在http://www.regular-expressions.info/javascriptexample.html上测试a@b.com时,这会产生混乱。 - dsdsdsdsd
2
我发现了这个问题。乍一看,它允许任意数量的电子邮件地址,没有分隔符,后面跟着任意数量的分号,每个分号后面至少有一个字符。所以这是有效的: "example@domain.comexample2@domain.com;$;8;asdf"。如何解决这个问题?需要帮助。 - Coder
1
@Evan Mulawski:那你为什么要使用这个正则表达式呢? - Coder
显示剩余10条评论

7

“你就是把这个当成刀子???” ——《鳄鱼邓迪》

实际上,所有这些都是非常糟糕的邮件地址匹配模式。要严格验证符合RFC 5322标准的电子邮件地址,确保个假阴性和个假阳性,您需要使用以下精确模式:

  (?x)

  (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)  # finally, match a mail address

我在这个回答中更详细地讨论了这个问题。

这需要使用Perl兼容的正则表达式(PCRE)库或者Perl本身才能正常工作。我不能保证不兼容perl的模式引擎能正确处理递归。


当然,这个问题是关于一个用分隔符分隔的电子邮件地址列表的。 - miken32

6
@Evan的答案接近,但该表达式匹配了以下无效情况:
1. `a@test.comb@test.comc@test.com`(没有定界符) 2. `a@test.com;b@test.com.c@test.com`(句点 `.` 被接受为定界符) 3. `a@test.com;b@test.comc@test.com`(只匹配第一个定界符 - 问题#1的扩展)
为了解决这些问题(并稍微简化一下),我进行了以下更改:
1. 删除了第一个电子邮件地址周围的第三个加号标志和外部括号 `()` 2. 将 `[;.]` 更改为普通的分号定界符 `;` - 实际上,我将该部分更改为 `;[ ]{0,1}`,因为我希望表达式在分号定界符后匹配空格。 3. 类似于#1,在定界符(步骤#2)和最终带有星号的右括号 `)*` 之间删除了表达式中最后一个加号标志和外部括号 `()`。
这是最终的表达式(允许在分号定界符后添加可选空格):
/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25}(;[ ]{0,1}([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})*$/

2
我已经点赞了,因为我发现这很有帮助,但是我会根据自己的需要进行调整。域名中不允许使用下划线,所以这是一个调整。标准(和我的雇主)允许在本地部分使用撇号,这是有效的,但对许多系统来说非常棘手,因此我也会添加这些内容,并且可能还需要添加对其他一些较少见字符的支持。 - Steve Lovell

3
我使用这个:

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25}(($)|( *;+ *$)|( *;+ *(?=[a-zA-Z0-9_\-\.]))))*$

https://regexr.com/3gth7


这个实际上允许在末尾使用可选的分号,正如最初的问题所要求的那样。点赞! - Joe Coyle

0

我需要允许定界符周围存在空格,所以我使用了 Evan Mulawski 答案的这个修改版本:

^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+(\s*[;.]\s*(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$

在此测试:http://regexlib.com/RETester.aspx?regexp_id=13126


-1
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

哇,这些正则表达式真的很复杂,而你的比其他人的还要复杂。如果你能描述一下你添加了什么以及它是如何工作的话,那会非常有帮助。 - joanis
有一个网页链接,可能提供了背景信息,但被管理员编辑掉了。 - tripleee
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
这个链接是这个Reg的来源,但是一个mod把它删除了,让情况变得更糟。我同意我本可以添加一点描述,但是删除信息只会让情况变得更糟。 - Jorge Cornejo Bellido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接