中文自然语言处理系列之一:正则匹配


本文汇总了部分中文自然语言处理中常用的,比较复杂的正则表达式,但并不是都是原创,部分引用了现有的网络资源,特此声明。


       相对其他语言的自然语言处理的领域,中文自然语言处理有其独特之处。即使是中文文本的处理,就有很多特有的处理细节。在中文文本处理时,经常需要用到许多正则表达式,而部分正则表达式的设计需要丰富的中文文本处理经验,才能在处理不同来源的文本时保持良好的性能。笔者收集了一些中文文本处理时常用的正则表达式,这些正则表达式都是经过精心设计的,性能也经过长期的测试验证,有着良好的实用效果。

1. 邮箱地址

       邮箱地址一般可分为三个部分,用户名,@符号,以及邮箱服务的域名,形如:username@example.com,其中用户名的字符限制在大小写字母(a-zA-Z),数字(0-9),下划线(_),横线(-)以及英文句号(.),并开头必须是字母,而域名则至少有顶级域名及一级域名。因此邮箱地址的正则表达式需要考虑其组成结构以及用户名和域名的组成,其正则表达式如下:

([\w\d_\.\-]+)@([\w\d\-]+)(\.[\w\d\-]+)*(\.[\w\d]{2,6})

       邮箱地址的正则表达式的结构分解如下图所示:

图1 邮箱地址的正则表达式的结构

2. 手机号码

       对于国内手机号码的正则表达式,Github的项目ChinaMobilePhoneNumberRegex针对不同的需求,设计了对应的正则表达式,本文选取了该项目提供的匹配所有手机号码的正则表达式。而关于国内手机号码的详细说明可以参考维基百科的文章,此处只作简要的介绍。

       手机号码一般由十一位数字组成,有时还会加上国际区号,具体的组成如下表所示:

位数 含义 说明
- 国际区号 +86
1~3位 网络识别号 手机运营商,每个运营商分配有不同的字段,都以1开头
4~7位 地区编码 识别手机归属地
8~11位 用户号码 随机分配

网络识别号均是由特别的数字编号组成的,目前只有有限的数字编号,但不时会新增,具体可以参考维基百科的文章

       考虑国际区号,手机号码的正则表达式如下所示:

(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[35678]\d{2}|4(?:0\d|1[0-2]|9\d))|9[189]\d{2}|66\d{2})\d{6}

       同样给出手机号码的正则表达式的结构解析:

图2 手机号码的正则表达式的结构

3. URL

       URL相对比较复杂,要设计比较通用的URL匹配正则表达式确实是比较困难的事。无意中发现的一篇博文专门对URL的匹配正则表达式的设计进行了研究,分别给出了通用的URL匹配正则表达式和网站URL的匹配正则表达式,其中通用的URL正则表达式如下所示:

((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))

       博文同样给出了URL的匹配正则表达式的组成结构,具体说明如下:

(                                             # 开始匹配整个URL
    (?:
        [a-z][\w-]+:                          # URL的协议及冒号
            (?:
                /{1,3}                        # 1-3斜杠
                |                             # 或者
                [a-z0-9%]                     # 单个字母,数字或者百分号
             )
        |                                     # 或者
        www\d{0,3}[.]                         # 万维网符号,如"www.","www1.", "www2." 等
        |                                     # 或者
        [a-z0-9.\-]+[.][a-z]{2,4}/            # 类似于域名加上斜杠
    )
    (?:                                       # 一个或多个组
        [^\s()<>]+                            # 没有空格以及-,(,),<,>中的任意一个字符
        |                                     # 或者
        \(([^\s()<>]+|(\([^\s()<>]+\)))*\)    # 两级括号对
     )+
     (?:                                      # URL结尾
         \(([^\s()<>]+|(\([^\s()<>]+\)))*\)   # 两级括号对
        |                                     #   或者
        [^\s`!()\[\]{};:'".,<>?«»“”‘’]        # 无空格及英文标点
     )
)

       上述URL的正则表达式可用于URL的匹配,但如果需要对URL进行解析,可参考Github上的项目js-url

4. 身份证号

       常见的身份证号码为十八位,但早期的身份证号码是十五位数,后来考虑到千年虫的问题,有添加了18位身份证的号码编制规则。其中十八位的身份证的组成如下表所示:

含义 位数 约束
省、自治区、直辖市代码 1~2位 起始数字不为0
地级市、盟、自治州代码 3~4位 -
县、县级市、区代码 5~6位 -
出生年月日 7~14位 日期格式
顺序号 15~17位 17位奇数为男,偶数为女
校验码 18位 数字或者字母X

十五身份号码与十八位身份证号码的区别有两处,其一是十五位身份证号码的年的编码只有两位,其二是没有最后的校验码,就比十八位的身份证少了三位数字。

       十八位身份证号码的匹配正则表达式如下:

[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]

其结构分解如下图所示:

图3 十八位身份证号码的正则表达式的结构

       十五位身份证号码的匹配正则表达式如下:

[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}

其结构分解如下:

图4 十五位身份证的正则表达式的结构

将两个正则表达式结合在一起,便可得到最终完整的身份证的匹配正则表达式了。

       最后推荐几个调试正则表达式的网站:Regular Expressions 101RegExrDebuggex

持续更新中

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 6,518评论 0 9
  • 忘了从哪收集的资料了,放这儿,以备不时之需。 只能输入数字:"^[0-9]*$"。 只能输入n位的数字:"^\d{...
    study_monkey阅读 5,259评论 0 7
  • 在每个死胡同的尽头,都有另一个维度的天空。 | 廖一梅 | 你像一片阳光,融化了我内心执拗的整座冰山。 1. 开头...
    _婧雯阅读 4,485评论 1 3
  • 我要写一万首诗给你 只希望你冲我一笑,并知道 我曾经一万天的飘摇 只为这一天能抓住夕阳的衣角 带我重回梦中的地方 ...
    泰安左眼皮跳跳阅读 1,342评论 0 7

友情链接更多精彩内容