允许在正则表达式中使用 "+" 来验证电子邮件地址。

9

正则表达式让我感到困惑。我该如何更改它以验证带有加号的电子邮件?这样我就可以使用test+spam@gmail.com进行注册。

if(!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$/i", $_GET['em'])) {

那个正则表达式在那个电子邮件地址上奏效了。你试过了吗? - Jeff
6个回答

42
似乎您目前并不熟悉正则表达式的工作原理,这是修改之前的第一步。让我们使用电子邮件地址john.robert.smith@mail.com来详细了解您的正则表达式(在下面的每个部分中,加粗的部分是该部分匹配的内容):
  1. ^ 是字符串的开头锚点。 它指定任何匹配必须从字符串开头开始。 如果模式没有被锚定,正则表达式引擎可以匹配子字符串,这通常是不希望的。

    锚点是零宽度的,意味着它们不捕获任何字符。

  2. [_a-z0-9-]+ 由两个元素组成,一个字符类和一个重复修饰符:

    • [...] 定义了一个字符类,告诉正则表达式引擎,这些字符中的任何一个都是有效的匹配项。在这种情况下,该类包含字母a-z、数字0-9以及破折号和下划线(一般来说,字符类中的破折号定义了一个范围,所以你可以使用 a-z 来代替 abcdefghijklmnopqrstuvwxyz;当作为类中的最后一个字符时,它充当一个文字破折号)。
    • + 是一个重复修饰符,指定前面的标记(在本例中是字符类)可以重复一次或多次。还有另外两个重复运算符:* 匹配零次或多次;? 匹配零次或一次(即使某些内容是可选的)。

    (捕获john.robert.smith@mail.com)

  3. (\.[_a-z0-9-]+)* 再次包含一个重复的字符类。它还包含一个和一个转义字符:

    • (...) 定义了一个组,允许你将多个标记分组在一起(在本例中,该组将作为整体重复)。假设我们想要匹配 'abc',零次或多次(即 abcabcabc 匹配,abcccc 不匹配)。如果我们尝试使用模式 abc*,重复修饰符将仅适用于 c,因为c 是修饰符之前的最后一个标记。为了解决这个问题,我们可以分组 abc ((abc)*),在这种情况下,修改器将应用于整个组,就像它是单个标记一样。
    • \. 指定一个文字点字符。这是必需的原因是因为 . 是正则表达式中的特殊字符,表示任何字符。由于我们想匹配实际的点字符,所以我们需要对它进行转义。

    (捕获john.robert.smith@mail.com)

  4. @ 不是正则表达式中的特殊字符,因此像所有其他非特殊字符一样,它匹配文字。
    (捕获 john.robert.smith@mail.com)

  5. [a-z0-9-]+ 再次定义了一个重复的字符类,就像上面的第2个项目一样。
    (捕获 john.robert.smith@mail.com)

  6. (\.[a-z0-9-]+)* 几乎与上面的第3个模式完全相同。
    (捕获 john.robert.smith@mail.com)

  7. $


    考虑到这一点,如何添加一个包含捕获加号段的部分应该更清晰了。正如我们在上面看到的,+是一个特殊字符,因此必须进行转义。接下来,由于+后面必须跟着一些字符,我们可以定义一个包含所需匹配字符的字符类,并定义其重复。最后,我们应该使整个组是可选的,因为电子邮件地址不需要有+段落:
    (\+[a-z0-9-]+)?
    

    当插入到你的正则表达式中时,它会像这样:
    /^[_a-z0-9-]+(\.[_a-z0-9-]+)*(\+[a-z0-9-]+)?@[a-z0-9-]+(\.[a-z0-9-]+)*$/i
    

保留 . 好不好?它不应该放在 [] 里面吗? - wesbos
我的当前正则表达式显示为(.[_a-z0-9-]+),我应该将其改为(+.[_a-z0-9-]+吗? - wesbos
啊,所以*表示0个或多个重复该模式? - wesbos
3
那是一个很棒的解释!+1 - Drewdin
此响应将 myemail@s 识别为有效电子邮件。 - Daniel Falabella
显示剩余3条评论

8

3
如果我能给你十个+1的话,我会这么做。 - CanSpice
这是 JavaScript 的 RFC 822,网址为 http://badsyntax.co/post/javascript-email-validation-rfc822。 - Gavin

2

我曾经使用这个正则表达式来验证电子邮件地址,在包含+的电子邮件地址上运行良好:

/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

这似乎很好,但它允许一些不应该出现在电子邮件地址中的其他字符。 - Imnotapotato
@RickSanchez,令人沮丧的现实是,正则表达式并不是解析/验证完整电子邮件地址的正确工具。 - Matt Ball

1

\+将匹配一个字面上的加号,但请注意:根据RFC规范,您仍然无法接近匹配所有可能的电子邮件地址,因为实际的正则表达式是疯狂的。这几乎肯定不值得;您应该使用真正的电子邮件解析器。


0
这是另一种解决方案(类似于David找到的解决方案):
//Escaped for .Net
^[_a-zA-Z0-9-]+((\\.[_a-zA-Z0-9-]+)*|(\\+[_a-zA-Z0-9-]+)*)*@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*(\\.[a-zA-Z]{2,4})$

//Native
^[_a-zA-Z0-9-]+((\.[_a-zA-Z0-9-]+)*|(\+[_a-zA-Z0-9-]+)*)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$

0

这是另一种解决方案

/^[_a-z0-9-+]+(\.[_a-z0-9-+]+)*(\+[a-z0-9-]+)?@[a-z0-9-.]+(\.[a-z0-9]+)$/

or For razor page(@=\u0040)

/^[_a-z0-9-+]+(\.[_a-z0-9-+]+)*(\+[a-z0-9-]+)?\u0040[a-z0-9-.]+(\.[a-z0-9]+)$/


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