格式化 Unicode 的 Unicode 表示?

Unicode representation to formatted Unicode?

我在理解 unicode 表达式到各自字符的翻译时遇到了一些困难。我一直在查看 unicode 规范,我遇到过各种格式如下 U+1F600 的字符串。据我所知,似乎没有内置函数知道如何将这些字符串转换为 Python 的正确格式,例如 \U0001F600

在我的程序中,我制作了一个小的正则表达式,它将找到这些 U\+.{5} 模式并将 U+ 替换为 \U000。但是,我发现此语法对于所有 unicode 字符都不相同,例如实际上应该从 U+200D 转换为 \u200D 的零宽度连接。

因为我不知道正确的 unicode 转义序列的每个变体,处理这种情况的最佳方法是什么?是我只能检查有限数量的这些特殊字符,还是我完全以错误的方式处理这个问题?

Python 版本为 2.7.

我认为您最可靠的方法是将数字解析为整数,然后使用 unichr 查找该代码点:

unichr(0x1f600)  # or: unichr(int('1f600', 16))

注:上Python3,就是chr

您可以查看 json 模块实现。好像没那么简单:

# Unicode escape sequence
uni = _decode_uXXXX(s, end)
end += 5
# Check for surrogate pair on UCS-4 systems
if sys.maxunicode > 65535 and \
0xd800 <= uni <= 0xdbff and s[end:end + 2] == '\u':
    uni2 = _decode_uXXXX(s, end + 1)
    if 0xdc00 <= uni2 <= 0xdfff:
        uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
        end += 6
char = unichr(uni)

(来自 cpython-2.7.9/Lib/json/decoder.py 129-138 行)

我认为直接使用json.loads会更容易:

>>> print json.loads('"\u0123"')
ģ

U+NNNN 只是用来谈论 Unicode 的常用符号。 Python 单个 Unicode 字符的语法是以下之一:

  • u'\xNN' 对于 Unicode 字符到 U+00FF
  • u'\uNNNN' Unicode 字符通过 U+FFFF
  • u'\U00NNNNNN' Unicode 字符到 U+10FFFF(最大)

注:N为十六进制数。

输入字符时使用正确的符号。即使对于低字符,您也可以使用更长的符号:

u'A' == u'\x41' == u'\u0041' == u'\U00000041'

以编程方式,您还可以使用 unichr(n) (Python 2) 或 chr(n) (Python 3) 生成正确的字符。

请注意,在 Python 3.3 之前,Python 有 narrowwide Unicode 版本。 unichr/chr 只能支持 sys.maxunicode,在窄版本中为 65535 (0xFFFF),在宽版本中为 1114111 (0x10FFFF)。 Python 3.3 统一了构建并解决了 Unicode 的许多问题。

如果您正在处理 U+NNNN 格式的文本字符串,这里是一个正则表达式 (Python 3)。它查找 U+ 和 4-6 个十六进制数字,并将它们替换为 chr() 版本。请注意,ASCII 字符 (Python 2) 或可打印字符 (Python 3) 将显示实际字符而不是转义版本。

>>> re.sub(r'U\+([0-9A-Fa-f]{4,6})',lambda m: chr(int(m.group(1),16)),'testing U+1F600')
'testing \U0001f600'
>>> re.sub(r'U\+([0-9A-Fa-f]{4,6})',lambda m: chr(int(m.group(1),16)),'testing U+5000')
'testing \u5000'
>>> re.sub(r'U\+([0-9A-Fa-f]{4,6})',lambda m: chr(int(m.group(1),16)),'testing U+0041')
'testing A'
>>> re.sub(r'U\+([0-9A-Fa-f]{4,6})',lambda m: chr(int(m.group(1),16)),'testing U+0081')
'testing \x81'