查看: 2302|回复: 7

[胡扯] 语言控请进·如何从一堆文字中扫描电邮地址?

  [复制链接]
梦石
0
星屑
1580
在线时间
1564 小时
注册时间
2008-7-30
回帖
4207

贵宾

发表于 2010-11-14 08:38:40 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 DeathKing 于 2010-11-14 08:38 编辑

正则式匹配有难度啊……经常遇到中文和邮箱连着的情况,因为邮箱地址的长度不定,老是要把无关字符扫描进去……
梦石
0
星屑
50
在线时间
66 小时
注册时间
2009-2-13
回帖
350
发表于 2010-11-14 09:41:56 | 显示全部楼层
本帖最后由 38571240 于 2010-11-14 09:42 编辑

根据长度?为什么不把能找到的后缀都列入?但@前面MS不可能确定
回复

使用道具 举报

巫女会长

梦石
0
星屑
60
在线时间
1028 小时
注册时间
2009-10-24
回帖
3425

贵宾

发表于 2010-11-14 09:53:24 | 显示全部楼层
我看到正则式三个字就知道我走错了
回复

使用道具 举报

梦石
0
星屑
1580
在线时间
1564 小时
注册时间
2008-7-30
回帖
4207

贵宾

 楼主| 发表于 2010-11-14 10:16:19 | 显示全部楼层
回复 38571240 的帖子

对啊,无论前面和后面,处理起来都很麻烦的说。

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
回复

使用道具 举报

梦石
0
星屑
59
在线时间
84 小时
注册时间
2008-4-19
回帖
403
发表于 2010-11-14 11:11:11 | 显示全部楼层
/(\w+)@((?:[-a-z0-9]+\.)+[a-z]{2,})/i
用这个试试
好吧这是II让我贴的- -
回复

使用道具 举报

梦石
0
星屑
50
在线时间
29 小时
注册时间
2007-5-7
回帖
230
发表于 2010-11-14 12:22:39 | 显示全部楼层
输入输出邮箱的时候前后加上分隔符?
(不懂正则的路过
回复

使用道具 举报

梦石
0
星屑
100
在线时间
0 小时
注册时间
2010-11-14
回帖
4
发表于 2010-11-14 14:04:07 | 显示全部楼层
看啊看···············
回复

使用道具 举报

梦石
0
星屑
310
在线时间
953 小时
注册时间
2007-4-25
回帖
798
发表于 2010-11-14 14:57:19 | 显示全部楼层
http://en.wikipedia.org/wiki/Email_address#Syntax

以上是电子邮箱地址的语法,正式语法定义在 RFC 5321、5322。
local-part@domain

其中提到:local-part 的长度上限为 64。

有效的 local-part:
Uppercase and lowercase English letters (a–z, A–Z)
Digits 0 to 9
Characters ! # $ % & ' * + - / = ? ^ _ ` { | } ~
Character . (dot, period, full stop) provided that it is not the first or last character, and provided also that it does not appear two or more times consecutively (e.g. John..Doe@example.com).
Additionally, quoted-strings (e.g., "John Doe"@example.com) are permitted, thus permitting characters otherwise prohibited.


domain 可以是一个有效的主机名,定义:
Hostnames are composed of series of labels concatenated with dots, as are all domain names.
...
Each label must be between 1 and 63 characters long, and the entire hostname (including the delimiting dots) has a maximum of 255 characters.
The Internet standards for protocols mandate that component hostname labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), the digits '0' through '9', and the hyphen ('-'). The original specification of hostnames in RFC 952, mandated that labels could not start with a digit or with a hyphen, and must not end with a hyphen. However, a subsequent specification (RFC 1123) permitted hostname labels to start with digits.

这里我们以 RFC 1123 定义的主机名为标准。

domain 同时也可以是 IP 地址:
In addition, the domain part may be an IP address literal, surrounded by square braces ...


IPv4 地址语法由 RFC 1918 定义,简单地说即是以句号分隔的四个 8 位无符号整数。

同时,根据 IP 标准,电子邮箱地址整体长度不得超过 254。

尝试写了一下:
  1. #coding: GBK

  2. # local-part@domain

  3. local_char = '(?:[a-zA-Z0-9!#\$\%&\'*/=?^_`{|}~-])'
  4. domain_label = '(?:[a-zA-Z0-9]+(?:-+[a-zA-Z0-9]+)*)'
  5. zero_to_255 = '(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])'

  6. $pattern = %r<

  7. # local-part
  8. (?:(?:#{local_char}+(?:\.#{local_char}+)*)|".*")
  9. @
  10. # domain
  11. (?:#{domain_label}(?:\.#{domain_label})*|\[#{zero_to_255}(?:\.#{zero_to_255}){3,3}\])

  12. >x

  13. def assert_match(str, expected)
  14.         if !(expected ^ (str[$pattern] != str))
  15.                 puts "预期#{expected ? '要' : '不'}匹配:"
  16.                 puts str
  17.                 puts "结果#{expected ? '不' : '却'}匹配。"
  18.                 exit(1)
  19.         end
  20. end

  21. assert_match('user@example.com', true)
  22. assert_match("66rpg.USER@66rpg.com", true)
  23. assert_match("death.king@test.com", true)
  24. assert_match(".deathking@test.com", false)
  25. assert_match("deathking.@test.com", false)
  26. assert_match('china.66rpg.forums.moderators.zh99998@66rpg.com.cn', true)
  27. assert_match('1993de?at!hk#i$n%g@localhost', true)
  28. assert_match('death>ki/ng@localhost', false)
  29. assert_match('e@t.c',true)
  30. assert_match('e@t.c.', false)
  31. assert_match('DEATHKING@66RPG.COM', true)
  32. assert_match('"雷欧纳德 sama 的邮箱哦>_<"@66rpg.net', true)
  33. assert_match('"!@#$%^&*"特殊字符君的邮箱哦%^&*<>:{"}"@example.org', true)
  34. assert_match('deathking@[127.0.0.1]', true)
  35. assert_match('deathking@192.168.0.1', true)                                 # 这是主机名
  36. assert_match('deathking@32768.1348.1083.19735', true)                         # 这也是主机名
  37. assert_match('deathking@[192.168.0,1]', false)
  38. assert_match('deathking@[8.0.8.256]', false)
  39. assert_match('deathking@[8.300.8.255]', false)
  40. assert_match('deathking@[8.30.260.255]', false)
  41. assert_match('deathking@[8.0.8.255]', true)
  42. assert_match('deathking@[-3.3.5.7]', false)
  43. assert_match('deathking@[192.168.178.123.]', false)

  44. puts '测试全部通过。'

  45. string = '大家好,我的名字叫Deathking,我的Email:是deathking03323@66rpg.cn哦,常联系!'
  46. puts string[$pattern]
复制代码
大概是这样。细微处还可以稍作调整,比如那些特殊字符,虽然标准允许,但大多数电子邮件客户端都不会允许。还可以加上 IPv6 的匹配。
长度上限在表达式中没有处理,因为据我所知,两级以上的动态长度的字元,同时又有长度限制的语言并非正则语言,所以正则表达式无法做到。静态长度的字元自然可以限制长度,如:
(?:.){1,63}
接受长度上限为 63 的字符串。但如果圆括号中的字元长度也是动态的,那正则表达式就无法描述了。

点评

厉害……⊙⊙  发表于 2010-11-14 15:14

评分

参与人数 1星屑 +194 收起 理由
zh99998 + 194 自觉投币。。

查看全部评分

su@rpg.blue:~> repeat 1 fortune
Matz is nice, so we are nice.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部