2009.11 27

用Javascript正则表达式验证Email地址

白天总是玩着不看书,这两晚却很神奇地因为睡不着起来看书,正则表达式。很好玩的东西。《Javascript 高级程序设计》是本好书,写得很系统。不过,在正则表达式那一章,看到验证电子邮件那里,似乎把正式表达式给写错了,也被我不小心发现了。

原代码是这样的:

function isValidMail(sText){
 var reMail = /^(?:\w+\.?)*\w+@(?:\w+\.?)*\w+$/;
 return reMail.test(sText);
}

似乎这样验证像sofish@163.com这样的邮箱是没问题的。但,由于仔细看一下在AT(@)后面的非捕获性引用中,使用的是*(出现任意次):

var reMail = /^(?:\w+\.?)*\w+@(?:\w+\.?)*\w+$/;

那么,也包括出现0次,这样的话。像sofish@163com这样的邮箱也是通过验证的。 显然,"."是必须至少出现一次的,因此,而"+"才表示至少出现一次。但这里,在AT后面,我们可以写像163.com.cn这样的结尾,但直接改成"+"的话,这样163..com.cn也可以通过验证。下面是我的方法:

function isValidMail(sText) {
 var reMail = /^(?:\w+\.?)*\w+@(?:\w+\.)+\w+$/;
 alert(reMail.test(sText))
}

规定"."号只出现一次。然后在非捕获引用后面,让其他至少显示1次,再以任意的字符结束。不过,这里的"\w"是包括下划线的,也就是说,像 sofish@163_.com_这样的邮件也是可能通过难的,显然,这是一个不合法的邮件,在AT后面的"."号后前,是不可以出现下划线的,而后面,只能是英文字母的(至少目前我没有见过用后面是数字的域名)。并且,这里应该注意到的是,"\w"所代表的字符包括下划线,不用缩写是这样的:

 [a-zA-Z_0-9]

因此,上面的代码可以这样进行改装:

function isValidMail(sText) {
 var reMail = /^(?:[a-z\d]+[_\-\+\.]?)*[a-z\d]+@(?:([a-z\d]+\-?)*[a-z\d]+\.)+([a-z]{2,})+$/i;
 alert(reMail.test(sText))
}

其实,通常这样写就可以了,对吧。要更深入,还可以考虑AT后面的各个点后面,不应该用相同的字母,比如.com.cn.com.cn(很显然,这样的域名还是有的,我错了,感谢@StonyWang同学的提醒,真的有人这么囧这样做么?)这样是不被请允许的。可以考虑一下利用捕获性引用进行储存,并进行比较验证。当做一道练习题吧(突然感觉好像在学高中的数学题)。

你可能需要的:测试性预览 | 源代码 (ctrl+U)

30 Other Comments

35

  1. 2009.11.27 1:08 pm
    Leeiio(visit): [回复]

    呃,沙发党~最近js水平精进不少吧~

  2. 2009.11.27 1:10 pm
    Leeiio(visit): [回复]

    呃,请问34532@etwet.com邮箱哪里错了。。你的demo提示false

  3. 2009.11.27 1:13 pm
    sofish(visit): [回复]

    @Leeiio: er…超快的你。上传出错,刷新一下就OK了,哦也。

  4. 2009.11.27 1:19 pm
    Leeiio(visit): [回复]

    @sofish: 速度快说明人家在关注你嘛,讨厌~

  5. 2009.11.27 1:21 pm
    sofish(visit): [回复]

    @Leeiio: 阿里人果然风骚(其实我只想说一个字“骚”)…

  6. 2009.11.27 1:34 pm
    DemoJameson(visit): [回复]

    Demo 无法获取邮箱地址,所以无论输入什么都是 false

  7. 2009.11.27 2:09 pm
    underone(visit): [回复]

    完全看不懂的飘过…

  8. 2009.11.27 3:33 pm
    中農(visit): [回复]

    題目很明白,內容看不懂

  9. 2009.11.27 3:53 pm
    独孤逸辰(visit): [回复]

    var reMail = /^(?:\w+\.?)*\w+@(?:\w+\.{1}){1}(?:\.\w+)?\w+$/;
    让domaim.com出现一次,后面最多一次.cn的形式。

  10. 2009.11.27 3:55 pm
    welee(visit): [回复]

    呜呜呜,完全看不懂…泪奔~

  11. 2009.11.27 4:07 pm
    nil(visit): [回复]

    验证邮箱的最佳方式是给那个邮箱发验证链接……

  12. 2009.11.27 4:31 pm
    sofish(visit): [回复]

    @DemoJameson: 解决了,我在firefox上测试,又多次刷新,忽略了input改变的值;

    @独孤逸辰: 像你这样写的话,abc@comm..cn_这样的邮件也可以通过验证,显然不能这样写。

  13. 2009.11.27 5:23 pm
    ZH CEXO(visit): [回复]

    这次,我上次看过来着,没像你这样深入去研究

  14. 2009.11.27 6:28 pm
  15. 2009.11.27 8:02 pm
  16. 2009.11.27 8:35 pm
    Lorz小朋友说(visit): [回复]

    嘿嘿,现个丑
    /^[a-zA-Z0-9](?:[._+]?[a-zA-Z0-9]+)*@(?:[a-zA-Z0-9](?:\-?[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,5}$/

    其实 @ 后面不就是主机吗,我估计应该可以用 IP 和 机器名字以及IPv9格式地址,不过不常见了

  17. 2009.11.27 10:12 pm
    sofish(visit): [回复]

    @Sparanoid: errr…囧。我直接忽略了-+这些。已经修正。

    @Lorz小朋友说: 果然在是细心的孩子。还考虑到{2,5}(后缀最多只有5位的么?)你的提醒让我大修一下代码。

    你的代码前面少了一个“-”,后面域名后缀的点之前是可以加“-”和”_”的。

  18. 2009.11.27 10:21 pm
    凯尔(visit): [回复]

    有几个小问题要指出一下,
    第一,[]中可以无视转义,可以直接写点号,dash,
    第二,英文大小写,可以用/a-z/i
    第三,用户名的逻辑太乱了,其实符号也可以都写到[]里

    AT后的内容,可以无视了,只要注意结尾的情况。

    这里来说,思路有点混乱,这里给一个email的正则:
    /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i

  19. 2009.11.27 10:30 pm
    sofish(visit): [回复]

    @凯尔: 嘿嘿,多谢赐教!正则表达式是一个可以学到很深的东西。似乎“%”这个有点奇怪。

    你给的这个匹配起来可能有点问题,比较@abc.cdf.com这样的东西。

  20. 2009.11.27 10:40 pm
    sofish(visit): [回复]

    @凯尔: 另外,我在[]里面没有转义的话,似乎DW会提示错误。当然这个是机器,可以忽略掉。只是,如果可以忽略转,那么我上面的代码,因为有“\”,那么,可以出现这样的邮件abc\cdf@com.cn这样的邮件。但,刚才我提示不可以。

  21. 2009.11.27 10:55 pm
    独孤逸辰(visit): [回复]

    ^(?:\w+\.?)*\w+@(?:\w+\.\w+){1}(?:\.\w+)?\w+$

  22. 2009.11.27 10:58 pm
    sofish(visit): [回复]

    @独孤逸辰: 还要注意\w,你看_abc@com.cn的邮箱也可以匹配到。

  23. 2009.11.28 8:03 am
    Lorz(visit): [回复]

    @sofish:

  24. 2009.11.28 8:07 am
    Lorz(visit): [回复]

    @sofish: 好像,域名里面不可以有下划线的吧。这个域名后缀 嘛,travel 就已经是6个了,没想到这个

  25. 2009.11.28 9:06 am
    独孤逸辰(visit): [回复]

    @sofish: 晕,把\w换成(?:[a-z\d]+[_\-\+\.]?),呵呵,还不知道不能用数字下划线开头。。

  26. 2009.11.28 10:01 am
    sofish(visit): [回复]

    @Lorz: er…似乎是哦,囧。

  27. 2009.11.28 10:34 am
    牤子(visit): [回复]

    我调试了,不能用啊

  28. 2009.11.28 11:23 am
    wordpress啦(visit): [回复]

    不错的JS文章,收藏

  29. 2009.11.29 10:26 am
    crossyou(visit): [回复]

    过来学习下,发现你的js水平越来越高了啊。

  30. 2009.12.24 2:26 pm
    ixwebhosting中文(visit): [回复]

    看过一阵php的正则表达式,感觉还不错

  31. 2010.01.02 11:23 pm
    freetao(visit): [回复]

    看不太懂。。。

  32. 2010.01.02 11:26 pm
    freetao(visit): [回复]

    需要再发一次么?上一条不知道发表成功没。。

  33. 2010.01.02 11:27 pm
    freetao(visit): [回复]

    This comment was originally posted on Twitter
    这个是用插件实现吗?

  34. 2010.06.23 11:41 am
    The Day(visit): [回复]

    正则正则…看着头就好晕…

  35. 2010.08.06 10:05 am
    乔福(visit): [回复]

    这个正则有性能问题吧?输入40个1时候js响应超级慢

Additional comments powered by BackType