8

我在 python 3 中有一个字符串,其中有几个 unicode 表示形式,例如:

t = 'R\\u00f3is\\u00edn'

我想转换 t 以便在打印时它具有正确的表示形式,即:

>>> print(t)
Róisín

但是我只是取回了原始字符串。我已经尝试过 re.sub 和其他一些,但我似乎无法找到一种无需遍历每个字符即可更改这些字符的方法。最简单的方法是什么?

4

3 回答 3

16

您想使用内置编解码器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'而不是''),可能还有更多我没有想到的事情。但这应该给你的想法。

于 2012-12-10T02:06:40.270 回答
0

我很抱歉作为第二个答案发布,我没有评论 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)
于 2014-07-19T00:17:48.873 回答
0

首先,你要转换成什么是相当困惑的。

试想一下,您可能想要转换为“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
于 2012-12-10T02:03:39.447 回答