在使用Python的過程中,由於需求原因,我們經常需要在文本或者網頁元素中用Python正則表達式匹配中文,但是我們經常所熟知的正則表達式卻只能匹配英文,而對於中文編碼卻望塵莫及,於是我大量Google,幾經Baidu,花了兩個多個小時測試,終於發現解決的辦法。特記錄如下
從字符串的角度來說,中文不如英文整齊、規范,這是不可避免的現實。本文結合網上資料以及個人經驗,以 python 語言為例,稍作總結。歡迎補充或挑錯。通常我們可以使用 repr()函數查看字串的原始格式。這對於寫正則表達式有所幫助。
Python正則表達式的問題
更加詳細的Python正則表達式問題,請參見這里http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
Python 的 re模塊有兩個相似的函數:re.match(), re.search 。
兩個函數的匹配過程完全一致,只是起點不同。
match只從字串的開始位置進行匹配,如果失敗,它就此放棄;
如果你了解match的特性(在某些情況下比較快),大可以自由用它;如果不太清楚,search通常是你需要的那個函數。
從一堆文本中,找出所有可能的匹配,以列表的形式返回,這種情況用findall()這個函數。例子見后面的代碼。
UTF-8與unicode
UTF-8 是變長的,1-6個字節,少數是漢字每個占用3個字節,多數占用4個字節,正則式為[\x80-\xff]{3},這個都知道了吧。
unicode下,漢字的格式如\uXXXX,只要找到對應的字符集的范圍,就能匹配相應的字串,方便從多語言文本中挑出所需要的某種語言的文本。不過,對於像日文這樣的粘着語,既有中文字符,又有平假名片假名,或許結果會有所偏差。
兩種字符類可以並列在一起使用,例如,平假名、片假名、中文的放在一起,u"[\u4e00-\u9fa5\u3040-\u309f\u30a0-\u30ff]+",來自定義所需要匹配的文本。
匹配中文時,正則表達式和目標字串的格式必須相同。這一點至關重要。或者都用默認的utf8,此時你不用額外做什么;如果是unicode,就需要在正則式之前加上u""格式。
可以這樣定義unicode字符串:string=u"我愛正則表達式"。如果字串不是unicode的,可以使用unicode()函數轉換之。如果你知道源字串的編碼,可以使用newstr=unicode(oldstring, original_coding_name)的方式轉換,
例如 linux 下常用unicode(string, "utf8"),windows 下或許會用cp936吧
示例程序1
# -*- coding: utf-8 -*- import sys import re reload(sys) sys.setdefaultencoding('utf8') s=""" en: Regular expression is a powerful tool for manipulating text. zh: 漢語是世界上最優美的語言,正則表達式是一個很有用的工具 jp: 正規表現は非常に役に立つツールテキストを操作することです。 jp-char: あアいイうウえエおオ kr:정규 표현식은 매우 유용한 도구 텍스트를 조작하는 것입니다. """ print "原始utf8字符" #utf8 print "--------" print repr(s) print "--------\n" #非ansi re_words=re.compile(r"[\x80-\xff]+") m = re_words.search(s,0) print "非ansi字符" print "--------" print m print m.group() print "--------\n" #unicode s = unicode(s) print "原始unicode字符" print "--------" print repr(s) print "--------\n" #unicode chinese re_words = re.compile(u"[\u4e00-\u9fa5]+") m = re_words.search(s,0) print "unicode 中文" print "--------" print m print m.group() res = re.findall(re_words, s) # 查詢出所有的匹配字符串 if res: print "There are %d parts:\n"% len(res) for r in res: print "\t",r print print "--------\n" #unicode korean re_words=re.compile(u"[\uac00-\ud7ff]+") m = re_words.search(s,0) print "unicode 韓文" print "--------" print m print m.group() print "--------\n" #unicode japanese katakana re_words=re.compile(u"[\u30a0-\u30ff]+") m = re_words.search(s,0) print "unicode 日文 片假名" print "--------" print m print m.group() print "--------\n" #unicode japanese hiragana re_words=re.compile(u"[\u3040-\u309f]+") m = re_words.search(s,0) print "unicode 日文 平假名" print "--------" print m print m.group() print "--------\n" #unicode cjk Punctuation re_words=re.compile(u"[\u3000-\u303f\ufb00-\ufffd]+") m = re_words.search(s,0) print "unicode 標點符號" print "--------" print m print m.group() print "--------\n"
幾種主要非英文字符集的編碼范圍
下面是Google出現的幾種主要非英文字符集的編碼范圍
主要非英文語系字符范圍 |
||
范圍 | 編碼 | 說明 |
2E80~33FFh | 中日韓符號區 | 收容康熙字典部首、中日韓輔助部首、注音符號、日本假名、韓文音符,中日韓的符號、標點、帶圈或帶括符文數字、月份,以及日本的假名組合、單位、年號、月份、日期、時間等。 |
3400~4DFFh | 中日韓認同文字擴充A區 | 中日韓認同表意文字擴充A區,總計收容6,582個中日韓漢字。 |
4E00~9FFFh | 中日韓認同表意文字區 | 中日韓認同表意文字區,總計收容20,902個中日韓漢字。 |
A000~A4FFh | 彝族文字區 | 收容中國南方彝族文字和字根 |
AC00~D7FFh | 韓文拼音組合字區 | 收容以韓文音符拼成的文字 |
F900~FAFFh | 中日韓兼容表意文字區 | 總計收容302個中日韓漢字 |
FB00~FFFDh | 文字表現形式區 | 收容組合拉丁文字、希伯來文、阿拉伯文、中日韓直式標點、小符號、半角符號、全角符號等。 |
比如需要匹配所有中日韓非符號字符,那么正則表達式應該是^[\u3400-\u9FFF]+$
理論上沒錯, 可是我到msn.co.ko隨便復制了個韓文下來, 發現根本不對, 詭異
再到msn.co.jp復制了個’お’, 也不得行..
然后把范圍擴大到^[\u2E80-\u9FFF]+$, 這樣倒是都通過了, 這個應該就是匹配中日韓文字的正則表達式了, 包括我們臺灣省還在盲目使用的繁體中文
而關於中文的正則表達式, 應該是^[\u4E00-\u9FFF]+$, 和論壇里常被人提起的^[\u4E00-\u9FA5]+$很接近
需要注意的是論壇里說的^[\u4E00-\u9FA5]+$這是專門用於匹配簡體中文的正則表達式, 實際上繁體字也在里面, 我用測試器測試了下’中華人民共和國’, 也通過了, 當然, ^[\u4E00-\u9FFF]+$也是一樣的結果。
示例程序2
那么我們很多時候如果要匹配的內容如果既有中文也有英文,比如我們要匹配一個可以由中文字母以及一些其他字符組成的標題,該怎么寫呢,我么接着看下面的代碼
#!coding:utf-8 import re import sys # 測試匹配中文信息 def TestReChinese( ): source = u" 數據結構模版----單鏈表SimpleLinkList[帶頭結點&&面向對象設計思想](C語言實現)" temp = source.decode('utf8') print "同時匹配中文英文" print "--------------------------" xx = u"([\w\W\u4e00-\u9fff]+)" pattern = re.compile(xx) results = pattern.findall(temp) for result in results: print result print "--------------------------" print print print "只匹配中文" print "--------------------------" xx = u"([\u4e00-\u9fff]+)" pattern = re.compile(xx) results = pattern.findall(temp) for result in results: print result print "--------------------------" if __name__ == "__main__" : # 測試正則表達式 reload(sys) sys.setdefaultencoding("utf-8") TestReChinese( )
其他方法
上面的代碼我們已經看的很明白了,這樣我們就很清楚了,那么有沒有其他方法呢,其實Python中也有一個其他方法可以解決中文匹配的問題了,但是這個寫法其實是繞過了編碼問題,也就是說是一種有點投機取巧的方法,但是這個方法卻很實用。
具體信息請參見http://blog.csdn.net/gatieme/article/details/43275077
轉:
https://blog.csdn.net/gatieme/article/details/43235791
\w 匹配的僅僅是中文,數字,字母,對於國人來講,僅匹配中文時常會用到,見下
匹配中文字符的正則表達式: [\u4e00-\u9fa5]
或許你也需要匹配雙字節字符,中文也是雙字節的字符
匹配雙字節字符(包括漢字在內):[^\x00-\xff]
注:可以用來計算字符串的長度(一個雙字節字符長度計 2,ASCII 字符計 1 )
PS:關於正則,本站還提供了一個非常簡便實用的正則測試工具供大家使用:
正則表達式在線測試工具://www.w3cschool.cn/tools/index?name=reg