前言
Python文件默認的編碼格式是ascii ,無法識別漢字,因為ascii碼中沒有中文。
所以py文件中要寫中文字符時,一般在開頭加 # -*- coding: utf-8 -*- 或者 #coding=utf-8。
這是指定一種編碼格式,意味著用該編碼存儲中文字符(也可以是gbk、gb2312等)。
關于測試的幾點注意 --------------------------------------------
注1:代碼中有中文,就要在頭部指定編碼方式,如果用編輯器寫代碼,還要注意IDE的文件存儲編碼格式(一般在setting)
注2:python3.x的源碼文件默認使用utf-8編碼,可以解析中文,開頭不指定也行,但為了規范和避免一些意想不到的問題,都指定一下為好
注3:linux交互式命令(左)和py文件(右)的運行結果會有不同:
左圖,因為我cmd設置了gbk編碼格式,所以u是s用gbk解碼后的unicode對象,配套的解編碼才能使原中文字符在print下正常顯示,所以再用gbk編碼;右圖,py文件指定了utf8編碼,所以u是s用utf8解碼后的unicode對象(其他方式會運行錯誤),而且想要在屏幕上打印出中文,還須encode成cmd設置的編碼(其他方式顯示亂碼)。
注4:測試中文字符的顯示和匹配時,最好用py文件寫,否則遇到兩邊不一樣的情況就會感到十分坑爹
----------------------------------------------------------------
下面實驗是基于python2.7和linux系統,不測試windows控制臺和windows下的IDE;
下面實驗是關于為了正常顯示中文和正則匹配中文的轉碼測試。
(一)python的str和中文字符串
簡單理解,編碼意味著 unicode -> ch-str,解碼意味著 ch-str -> unicode,
關于print顯示中文。舉個例子,用gb18030和utf-8編碼的內容相同的兩份文檔測試:
#coding=utf-8import syswith open('ch_input_gbk', 'r') as f1, open('ch_input_utf', 'r') as f2: for l1 in f1: lines = l1.strip().split('/t') # lines是list, 通過打印它可以看看str不同編碼的內容 sent = lines[0] # sent是ch-str print lines, sent for l2 in f2: lines = l2.strip().split('/t') sent = lines[0] print lines, sent print sent.decode('utf8').encode('gbk') #print str(sent).decode('string_escape').decode('utf8').encode('gbk')輸出:
['/xd3/xc4/xc8/xcb/xd6/xf1/xc9/xa3/xd4/xb0'] 幽人竹桑園['/xb9/xe9/xce/xd4/xbc/xc5/xce/xde/xd0/xfa'] 歸臥寂無喧['/xce/xef/xc7/xe9/xbd/xf1/xd2/xd1/xbc/xfb'] 物情今已見['/xb4/xd3/xb4/xcb/xd3/xfb/xce/xde/xd1/xd4'] 從此欲無言['/xe5/xb9/xbd/xe4/xba/xba/xe7/xab/xb9/xe6/xa1/x91/xe5/x9b/xad'] 騫戒漢绔規鍥幽人竹桑園['/xe5/xbd/x92/xe5/x8d/xa7/xe5/xaf/x82/xe6/x97/xa0/xe5/x96/xa7'] 褰掑崸瀵傛棤鍠歸臥寂無喧['/xe7/x89/xa9/xe6/x83/x85/xe4/xbb/x8a/xe5/xb7/xb2/xe8/xa7/x81'] 鐗╂儏浠婂凡瑙物情今已見['/xe4/xbb/x8e/xe6/xad/xa4/xe6/xac/xb2/xe6/x97/xa0/xe8/xa8/x80'] 浠庢嬈叉棤璦從此欲無言
line7,f1的sent正常顯示是因為,txt是gb18030編碼,讀入后仍為此(這與首行的#coding可不一樣),我的cmd同樣也是gb18030
line11,f2的sent亂碼顯示是因為,txt是utf8編碼,讀入后仍為此,但是print對str是按cmd設置的編碼格式解讀的
line12,sent又能正常顯示是因為,utf8解碼 -> unicode -> 編碼為gb18030,所以print可以正常解讀了
line13,有時讀入或抓取的中文不是/xd3/xc4而是這個樣子的//xd3//xc4,這是/被轉義了,對它無法做decode轉換編碼,先用str(sent).decode('string_escape'),把反斜杠的轉義去掉,然后就和第12行一樣了
附,12行如果直接寫 sent.encode('gbk') 會報錯:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0
是說,當前位置這個str不能被py默認的ascii解碼,因為它是中文str;要用它的實際編碼來解碼而不是ascii:
1 修改py默認編碼,由ascii改為當前str實際編碼(utf8或gb18030等)
reload(sys) sys.setdefaultencoding('utf8')2 但是讀入多個文檔含有多個編碼方式時,1的方法就不方便,還是對不同的ch-str都采用unicode轉換編碼較好 (上面例子中的方式)
(二)中文字符串的正則匹配
只有一項標準,匹配字符串和原字符串編碼統一,
還是舉例子,
# -*- coding: utf-8 -*- import re def findPart(regex, text, name): res = re.findall(regex, text) print "There are %d %s parts:" % (len(res), name) for r in res: print r.encode('gbk') sample = '''en: Regular expression is a powerful tool for manipulating text. zh: 正則表達式是一種很有用的處理文本的工具。 jp: 正規表現は非常に役に立つツールテキストを操作することです。 jp-char: あアいイうウえエおオ kr:?? ???? ?? ??? ?? ???? ???? ????. puc: ,。??。?.?!:《》%&*#<>%&*# ''' #convert the utf8 to unicode usample = unicode(sample,'utf8') #相當于usample = sample.decode('utf8') #get each language parts: findPart(u"[/u4e00-/u9fa5]+", usample, "unicode chinese") findPart(u"[/uac00-/ud7ff]+", usample, "unicode korean") findPart(u"[/u30a0-/u30ff]+", usample, "unicode japanese katakana") findPart(u"[/u3040-/u309f]+", usample, "unicode japanese hiragana") findPart(u"[/u3000-/u303f/ufb00-/ufffd]+", usample, "unicode cjk Punctuation") line20,目標字符串usample是unicode類型,故匹配字符串regex也要同(如u"[/u4e00-/u9fa5]+"),u就是轉成unicode;
line7,usample是unicode,要想print正確顯示,則需要r.encode('gbk'),根據cmd的編碼格式;
正則匹配規則不多述,[/u????-/u????] 是不同語言的unicode編碼段,該例輸出是,
中文6個part:正則表達式是一種很有用的處理文本的工具、正規表現、非常、役、立、操作
韓文8個part:??、????、??、???、??、????、????、????
日文片假名6個part:ツールテキスト、ア、イ、ウ、エ、オ
日文平假名11個part:は、に、に、つ、を、することです、あ、い、う、え、お
非英文標點4個part:。、。、,。?!:、《》%&*#
另外,簡單的正則匹配,舉幾個例子,
s1 = '天天天向上天天向上' print (re.sub(ur'[/u4e00-/u9fa5]{1,}', u'1', s1.decode('utf8'))).encode('gbk') # 1print (re.sub(ur'([/u4e00-/u9fa5])/1{1,}', u'1', s1.decode('utf8'))).encode('gbk') # 1向上1向上print (re.sub(ur'([/u4e00-/u9fa5])/1{2,}', u'1', s1.decode('utf8'))).encode('gbk') # 1向上天天向上s2 = '【aa】天天bb@cc'print (re.sub(ur'【.*】', u'1', s2.decode('utf8'))).encode('gbk') # 1天天bb@ccprint (re.sub(ur'@', u'1', s2.decode('utf8'))).encode('gbk') # 【aa】天天bb1ccline2,{1,}匹配1~n個前面表達式,故6個漢字全部匹配
line3,()內為一個group,/1指第一個group,{1,}要再匹配1~n個前面group內容(若group內是1個字, {1,}要匹配第2個及往后的字),故匹配了3個天和2個天
line6和7,中英文標點符號匹配,regex沒有轉義符的話可以不寫r,若text全是英文也可以不寫u
以上這篇淺談python下含中文字符串正則表達式的編碼問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答