2013-03-11 56 views
1

我有一个字符串(g),我运行一个简单的正则表达式来查找一个数字。问题是,不知何故正则表达式不适用于该字符串类型(编码?)。 但是,“正常”字符串可以正常工作。 我错过了什么?请参考下面的步骤上REPL所见:python正则表达式不能在字符串编码上工作

(例如是一个在线扑克锦标赛的总结)

不工作:

>>> g 
'F\x00u\x00l\x00l\x00 \x00T\x00i\x00l\x00t\x00 \x00P\x00o\x00k\x00e\x00r\x00 \x00T\x00o\x00u\x00r\x00n\x00a\x00m\x00e\x00n\x00t\x00 \x00S\x00u\x00m\x00m\x00a\x00r\x00y\x00 \x00$\x002\x00.\x002\x005\x00 \x00H\x00e\x00a\x00d\x00s\x00-\x00U\x00p\x00 \x00S\x00i\x00t\x00 \x00&\x00 \x00G\x00o\x00 \x00(\x002\x005\x000\x005\x005\x005\x009\x001\x004\x00)\x00 \x002\x00-\x007\x00 \x00T\x00r\x00i\x00p\x00l\x00e\x00 \x00D\x00r\x00a\x00w\x00 \x00L\x00i\x00m\x00i\x00t\x00 \x00(\x00T\x00u\x00r\x00b\x00o\x00,\x00 \x00H\x00e\x00a\x00d\x00s\x00 \x00U\x00p\x00)\x00\n\x00B\x00u\x00y\x00-\x00I\x00n\x00:\x00 \x00$\x002\x00.\x001\x002\x00 \x00+\x00 \x00$\x000\x00.\x001\x003\x00\n\x00B\x00u\x00y\x00-\x00I\x00n\x00 \x00C\x00h\x00i\x00p\x00s\x00:\x00 \x001\x005\x000\x000\x00\n\x002\x00 \x00E\x00n\x00t\x00r\x00i\x00e\x00s\x00\n\x00T\x00o\x00t\x00a\x00l\x00 \x00P\x00r\x00i\x00z\x00e\x00 \x00P\x00o\x00o\x00l\x00:\x00 \x00$\x004\x00.\x002\x004\x00\n\x00T\x00o\x00u\x00r\x00n\x00a\x00m\x00e\x00n\x00t\x00 \x00s\x00t\x00a\x00r\x00t\x00e\x00d\x00:\x00 \x002\x000\x001\x003\x00/\x000\x003\x00/\x000\x008\x00 \x000\x006\x00:\x000\x000\x00:\x002\x007\x00 \x00E\x00T\x00\n\x00T\x00o\x00u\x00r\x00n\x00a\x00m\x00e\x00n\x00t\x00 \x00f\x00i\x00n\x00i\x00s\x00h\x00e\x00d\x00:\x00 \x002\x000\x001\x003\x00/\x000\x003\x00/\x000\x008\x00 \x000\x006\x00:\x001\x004\x00:\x003\x000\x00 \x00E\x00T\x00\n\x00\n\x001\x00:\x00 \x00A\x00n\x00d\x00r\x00e\x00y\x003\x003\x001\x000\x00,\x00 \x00$\x004\x00.\x002\x004\x00\n\x002\x00:\x00 \x00s\x00y\x00n\x00t\x00h\x00e\x00s\x00i\x00i\x00s\x00\n\x00s\x00y\x00n\x00t\x00h\x00e\x00s\x00i\x00i\x00s\x00 \x00f\x00i\x00n\x00i\x00s\x00h\x00e\x00d\x00 \x00i\x00n\x00 \x002\x00n\x00d\x00 \x00p\x00l\x00a\x00c\x00e' 
>>> myre = re.compile(u"""\(([0-9]+)\)""",re.UNICODE) 
>>> m = myre.search(g) 
>>> m.groups() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'NoneType' object has no attribute 'groups' 

WORKING

>>> g="Full Tilt Poker Tournament Summary $2.25 Heads-Up Sit & Go (250555914) 2-7 Triple Draw Limit (Turbo, Heads Up)" 
>>> m = myre.search(g) 
>>> m.groups() 
('250555914',) 

回答

4

虽然没有BOM(字节顺序标记),但您有UTF-16编码数据。解码为Unicode首先试图匹配正则表达式之前:

>>> g[:-1].decode('utf-16-le') 
u'Full Tilt Poker Tournament Summary $2.25 Heads-Up Sit & Go (250555914) 2-7 Triple Draw Limit (Turbo, Heads Up)\nBuy-In: $2.12 + $0.13\nBuy-In Chips: 1500\n2 Entries\nTotal Prize Pool: $4.24\nTournament started: 2013/03/08 06:00:27 ET\nTournament finished: 2013/03/08 06:14:30 ET\n\n1: Andrey3310, $4.24\n2: synthesiis\nsynthesiis finished in 2nd plac' 
>>> myre.search(g[:-1].decode('utf-16-le')).groups() 
(u'250555914',) 

,我不得不删除最后一个字节,以使该解码不过,在最后一个空字节失踪。如果最后缺少数据,那么很可能也会丢失BOM所在的开始中的数据。 BOM告诉解码器什么样的UTF-16编码被用于编码(小端或大端),没有它我们需要明确地告诉Python将其解码为小端。

如果您解码完整数据(包括物料清单),则可以使用.decode('utf-16')代替。

如果从文件中读取,请使用codecs.open()代替,并Python的其解码为Unicode为您提供:

import codecs 

for line in codecs.open('filename.txt', 'r', encoding='utf16'): 
    # handle line 

因为否则的话之类的东西.readlines()在字节级,分别编码为分出两个新行字节就像UTF-16中的其他所有字节一样。

+0

谢谢@Martijn彼得斯,我仍然不明白为什么我打开(文件).readlines()而不是正常的utf-16格式时得到这种格式。你能帮助那个点吗? – jule64 2013-03-11 17:54:52

+1

不要在UTF-16编码的文件上使用'readlines()'!换行符也被编码为两个字节,现在正在分割文件。使用'codecs.open()'并读取Unicode数据。 – 2013-03-11 17:57:28

相关问题