【问题标题】:Python 3.8: Escape non-ascii characters as unicodePython 3.8:将非 ascii 字符转义为 unicode
【发布时间】:2021-04-13 13:14:07
【问题描述】:

我有可以包含非 ascii 字符的输入和输出文本文件。有时我需要转义它们,有时我需要编写非 ascii 字符。基本上,如果我得到“Bürgerhaus”,我需要输出“B\u00FCrgerhaus”。如果我得到“B\u00FCrgerhaus”,我需要输出“Bürgerhaus”。

一个方向很好:

>>> s1 = "B\u00FCrgerhaus"
>>> print(s1)
Bürgerhaus

但是在另一个方向上我没有得到预期的结果('B\u00FCrgerhaus'):

>>> s2 = "Bürgerhaus"
>>> s2_trans = s2.encode('utf8').decode('unicode_escape')
>>> print(s2_trans)
Bürgerhaus

我读到 unicode-escape 需要 latin-1,我尝试将其编码为它,但这也没有产生结果。我做错了什么?

(PS:感谢 Matthias 提醒我第一个示例中的转换是不必要的。)

【问题讨论】:

  • 您的第一个示例将字符串转换为 UTF-8,然后将其转换回 unicode。当然结果是一样的。试试print(s1),你会得到Bürgerhaus
  • @Matthias 我认为 OP 试图实现的是将他的字符串与 unicode char 转换为字符串表示形式,然后将其转换回来。即回到带有点代码的原始表示
  • 我现在也很好奇如何给定一个字符串Bürgerhaus你可以让python打印你的unicode转义版本B\u00FCrgerhaus
  • 这看起来很像 JSON 编码字符串的方式。你确定你真的不应该使用 json 库,而不是依赖脆弱的转义操作吗?

标签: python unicode encoding


【解决方案1】:

你可以这样做:

charList=[]
s1 = "Bürgerhaus"

for i in [ord(x) for x in s1]:
    # Keep ascii characters, unicode characters 'encoded' as their ordinal in hex
    if i < 128:  # not sure if that is right or can be made easier!
        charList.append(chr(i))
    else:
        charList.append('\\u%04x' % i )

res = ''.join(charList)
print(f"Mixed up sting: {res}")

for myStr in (res, s1):
    if '\\u' in myStr:
        print(myStr.encode().decode('unicode-escape'))
    else:
        print(myStr)

输出:

Mixed up sting: B\u00fcrgerhaus
Bürgerhaus
Bürgerhaus

解释:

我们要将每个字符转换为它对应的 Unicode 代码点。

print([(c, ord(c)) for c in s1])
[('B', 66), ('ü', 252), ('r', 114), ('g', 103), ('e', 101), ('r', 114), ('h', 104), ('a', 97), ('u', 117), ('s', 115)]

常规 ASCII 字符十进制值 = 128(详细表 here)。

现在,我们将使用相应的 unicode 表示“编码”所有 >= 128 的字符。

【讨论】:

  • 它有效,尽管我并不完全理解它。你能解释一下 if i
  • @Alv123:希望这样可以更清楚。
  • 这对于代码点高于 U+FFFF 的字符会中断。用表情符号试试:十六进制代码超过四位,但反转操作会去掉这些,导致文本乱码。
【解决方案2】:

您只能将decode() bytestrings (bytes) 转换为[unicode] 字符串,反之,encode() [unicode] 字符串转换为bytes

因此,如果您想解码使用unicode-escape 转义的字符串,您需要先将其转换为(encode())字节串,例如,使用您在问题中所写的latin1

>>> encoded_str = 'B\\xfcrgerhaus'
>>> encoded = encoded_str.encode('latin-1')
>>> encoded
b'B\\xfcrgerhaus'
>>> encoded.decode('unicode-escape')
'Bürgerhaus'
>>> _.encode('unicode-escape')
b'B\\xfcrgerhaus'
>>> _ == encoded
True

另请参阅:how do I .decode('string-escape') in Python3?

【讨论】:

    猜你喜欢
    • 2010-12-09
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    相关资源
    最近更新 更多