中文自然語言處理系列之一:正則匹配


本文匯總了部分中文自然語言處理中常用的,比較復(fù)雜的正則表達式,但并不是都是原創(chuàng),部分引用了現(xiàn)有的網(wǎng)絡(luò)資源,特此聲明。


? ? ? ?相對其他語言的自然語言處理的領(lǐng)域,中文自然語言處理有其獨特之處。即使是中文文本的處理,就有很多特有的處理細節(jié)。在中文文本處理時,經(jīng)常需要用到許多正則表達式,而部分正則表達式的設(shè)計需要豐富的中文文本處理經(jīng)驗,才能在處理不同來源的文本時保持良好的性能。筆者收集了一些中文文本處理時常用的正則表達式,這些正則表達式都是經(jīng)過精心設(shè)計的,性能也經(jīng)過長期的測試驗證,有著良好的實用效果。

1. 郵箱地址

? ? ? ?郵箱地址一般可分為三個部分,用戶名,@符號,以及郵箱服務(wù)的域名,形如:username@example.com,其中用戶名的字符限制在大小寫字母(a-zA-Z),數(shù)字(0-9),下劃線(_),橫線(-)以及英文句號(.),并開頭必須是字母,而域名則至少有頂級域名及一級域名。因此郵箱地址的正則表達式需要考慮其組成結(jié)構(gòu)以及用戶名和域名的組成,其正則表達式如下:

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

? ? ? ?郵箱地址的正則表達式的結(jié)構(gòu)分解如下圖所示:

圖1 郵箱地址的正則表達式的結(jié)構(gòu)

2. 手機號碼

? ? ? ?對于國內(nèi)手機號碼的正則表達式,Github的項目ChinaMobilePhoneNumberRegex針對不同的需求,設(shè)計了對應(yīng)的正則表達式,本文選取了該項目提供的匹配所有手機號碼的正則表達式。而關(guān)于國內(nèi)手機號碼的詳細說明可以參考維基百科的文章,此處只作簡要的介紹。

? ? ? ?手機號碼一般由十一位數(shù)字組成,有時還會加上國際區(qū)號,具體的組成如下表所示:

位數(shù) 含義 說明
- 國際區(qū)號 +86
1~3位 網(wǎng)絡(luò)識別號 手機運營商,每個運營商分配有不同的字段,都以1開頭
4~7位 地區(qū)編碼 識別手機歸屬地
8~11位 用戶號碼 隨機分配

網(wǎng)絡(luò)識別號均是由特別的數(shù)字編號組成的,目前只有有限的數(shù)字編號,但不時會新增,具體可以參考維基百科的文章

? ? ? ?考慮國際區(qū)號,手機號碼的正則表達式如下所示:

(?:\+?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}

? ? ? ?同樣給出手機號碼的正則表達式的結(jié)構(gòu)解析:

圖2 手機號碼的正則表達式的結(jié)構(gòu)

3. URL

? ? ? ?URL相對比較復(fù)雜,要設(shè)計比較通用的URL匹配正則表達式確實是比較困難的事。無意中發(fā)現(xiàn)的一篇博文專門對URL的匹配正則表達式的設(shè)計進行了研究,分別給出了通用的URL匹配正則表達式和網(wǎng)站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的匹配正則表達式的組成結(jié)構(gòu),具體說明如下:

(                                             # 開始匹配整個URL
    (?:
        [a-z][\w-]+:                          # URL的協(xié)議及冒號
            (?:
                /{1,3}                        # 1-3斜杠
                |                             # 或者
                [a-z0-9%]                     # 單個字母,數(shù)字或者百分號
             )
        |                                     # 或者
        www\d{0,3}[.]                         # 萬維網(wǎng)符號,如"www.","www1.", "www2." 等
        |                                     # 或者
        [a-z0-9.\-]+[.][a-z]{2,4}/            # 類似于域名加上斜杠
    )
    (?:                                       # 一個或多個組
        [^\s()<>]+                            # 沒有空格以及-,(,),<,>中的任意一個字符
        |                                     # 或者
        \(([^\s()<>]+|(\([^\s()<>]+\)))*\)    # 兩級括號對
     )+
     (?:                                      # URL結(jié)尾
         \(([^\s()<>]+|(\([^\s()<>]+\)))*\)   # 兩級括號對
        |                                     #   或者
        [^\s`!()\[\]{};:'".,<>???“”‘’]        # 無空格及英文標點
     )
)

? ? ? ?上述URL的正則表達式可用于URL的匹配,但如果需要對URL進行解析,可參考Github上的項目js-url

4. 身份證號

? ? ? ?常見的身份證號碼為十八位,但早期的身份證號碼是十五位數(shù),后來考慮到千年蟲的問題,有添加了18位身份證的號碼編制規(guī)則。其中十八位的身份證的組成如下表所示:

含義 位數(shù) 約束
省、自治區(qū)、直轄市代碼 1~2位 起始數(shù)字不為0
地級市、盟、自治州代碼 3~4位 -
縣、縣級市、區(qū)代碼 5~6位 -
出生年月日 7~14位 日期格式
順序號 15~17位 17位奇數(shù)為男,偶數(shù)為女
校驗碼 18位 數(shù)字或者字母X

十五身份號碼與十八位身份證號碼的區(qū)別有兩處,其一是十五位身份證號碼的年的編碼只有兩位,其二是沒有最后的校驗碼,就比十八位的身份證少了三位數(shù)字。

? ? ? ?十八位身份證號碼的匹配正則表達式如下:

[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]

其結(jié)構(gòu)分解如下圖所示:

圖3 十八位身份證號碼的正則表達式的結(jié)構(gòu)

? ? ? ?十五位身份證號碼的匹配正則表達式如下:

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

其結(jié)構(gòu)分解如下:

圖4 十五位身份證的正則表達式的結(jié)構(gòu)

將兩個正則表達式結(jié)合在一起,便可得到最終完整的身份證的匹配正則表達式了。

? ? ? ?最后推薦幾個調(diào)試正則表達式的網(wǎng)站:Regular Expressions 101RegExrDebuggex

持續(xù)更新中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 正則表達式到底是什么東西?字符是計算機軟件處理文字時最基本的單位,可能是字母,數(shù)字,標點符號,空格,換行符,漢字等...
    獅子挽歌閱讀 2,169評論 0 9
  • 忘了從哪收集的資料了,放這兒,以備不時之需。 只能輸入數(shù)字:"^[0-9]*$"。 只能輸入n位的數(shù)字:"^\d{...
    study_monkey閱讀 1,424評論 0 7
  • 在每個死胡同的盡頭,都有另一個維度的天空。 | 廖一梅 | 你像一片陽光,融化了我內(nèi)心執(zhí)拗的整座冰山。 1. 開頭...
    _婧雯閱讀 947評論 1 3
  • 我要寫一萬首詩給你 只希望你沖我一笑,并知道 我曾經(jīng)一萬天的飄搖 只為這一天能抓住夕陽的衣角 帶我重回夢中的地方 ...
    泰安左眼皮跳跳閱讀 151評論 0 7