我在 python 3 中有一个字符串,其中有几个 unicode 表示形式,例如:
t = 'R\\u00f3is\\u00edn'
我想转换 t 以便在打印时它具有正确的表示形式,即:
>>> print(t)
Róisín
但是我只是取回了原始字符串。我已经尝试过 re.sub 和其他一些,但我似乎无法找到一种无需遍历每个字符即可更改这些字符的方法。最简单的方法是什么?
我在 python 3 中有一个字符串,其中有几个 unicode 表示形式,例如:
t = 'R\\u00f3is\\u00edn'
我想转换 t 以便在打印时它具有正确的表示形式,即:
>>> print(t)
Róisín
但是我只是取回了原始字符串。我已经尝试过 re.sub 和其他一些,但我似乎无法找到一种无需遍历每个字符即可更改这些字符的方法。最简单的方法是什么?
您想使用内置编解码器unicode_escape
。
如果t
已经是一个bytes
(一个 8 位字符串),就这么简单:
>>> print(t.decode('unicode_escape'))
Róisín
如果t
已经解码为Unicode,您可以将其编码回a bytes
,然后decode
以这种方式编码。如果您确定您的所有 Unicode 字符都已转义,那么您使用什么编解码器进行编码实际上并不重要。否则,您可以尝试取回原始字节字符串,但它更简单,并且可能更安全,只强制任何未编码的字符进行编码,然后它们将与已经编码的字符一起解码:
>>> print(t.encode('unicode_escape').decode('unicode_escape')
Róisín
如果您想知道将来如何使用正则表达式做这种事情,请注意,它sub
可以让您传递一个函数而不是repl
. 并且您可以通过调用将任何十六进制字符串转换为整数int(hexstring, 16)
,并将任何整数转换为相应的 Unicode 字符chr
(请注意,这是 Python 2 中不同的一位 - 您需要unichr
)。所以:
>>> re.sub(r'(\\u[0-9A-Fa-f]+)', lambda matchobj: chr(int(matchobj.group(0)[2:], 16)), t)
Róisín
或者,让它更清楚一点:
>>> def unescapematch(matchobj):
... escapesequence = matchobj.group(0)
... digits = escapesequence[2:]
... ordinal = int(digits, 16)
... char = chr(ordinal)
... return char
>>> re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, t)
Róisín
编解码器unicode_escape
实际上处理\U
, \x
, \X
, 八进制 ( \066
) 和特殊字符 ( \n
) 序列以及 just \u
,并且它实现了仅读取适当的最大位数的适当规则(4 表示\u
,8 表示\U
等,因此r'\\u22222'
解码to'∢2'
而不是''
),可能还有更多我没有想到的事情。但这应该给你的想法。
我很抱歉作为第二个答案发布,我没有评论 abarnert 解决方案的声誉。
在使用他的函数处理大约 50K 的 android 字符串后,我注意到对于某些用例还有另一个小的改进。
我将 + 更改为 {1,4} 以处理有效十六进制字符跟随 4 位转义的情况。
我还将 int(escapesequence) 更改为读取 int(digits)
>>> def unescapematch(matchobj):
... escapesequence = matchobj.group(0)
... digits = escapesequence[2:]
... ordinal = int(digits, 16)
... char = unichr(ordinal)
... return char
>>> print re.sub(r'(\\u[0-9A-Fa-f]{1,4})', unescapematch, "Wi\u2011Fi")
Wi‑Fi
>>> print re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, "Wi\u2011Fi")
Traceback (most recent call last):
File "<pyshell#102>", line 1, in <module>
print re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, "Wi\u2011Fi")
File "C:\Python27\lib\re.py", line 151, in sub
return _compile(pattern, flags).sub(repl, string, count)
File "<pyshell#99>", line 5, in unescapematch
char = unichr(ordinal)
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
首先,你要转换成什么是相当困惑的。
试想一下,您可能想要转换为“o”和“i”。在这种情况下,您只需制作一张地图:
mp = {u'\u00f3':'o', u'\u00ed':'i'}
比您可以应用替换,例如:
t = u'R\u00f3is\u00edn'
for i in range(len(t)):
if t[i] in mp: t[i]=mp[t[i]]
print t