我如何在Python3中使用.decode('string-escape')?

vy3*_*y32 49 python escaping python-3.x

我有一些需要转义的转义字符串.我想用Python做这件事.

例如,在python2.7中,我可以这样做:

>>> "\\123omething special".decode('string-escape')
'Something special'
>>> 
Run Code Online (Sandbox Code Playgroud)

我如何在Python3中完成它?这不起作用:

>>> b"\\123omething special".decode('string-escape')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
LookupError: unknown encoding: string-escape
>>> 
Run Code Online (Sandbox Code Playgroud)

我的目标是成为一个像这样的字符串:

s\000u\000p\000p\000o\000r\000t\000@\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000
Run Code Online (Sandbox Code Playgroud)

把它变成:

"support@psiloc.com"
Run Code Online (Sandbox Code Playgroud)

在进行转换之后,我将探测我的字符串是用UTF-8还是UTF-16编码的.

Mar*_*ers 50

你必须使用unicode_escape:

>>> b"\\123omething special".decode('unicode_escape')
Run Code Online (Sandbox Code Playgroud)

如果你一个str对象开始(相当于python 2.7 unicode),你需要首先编码为字节,然后解码unicode_escape.

如果您需要字节作为最终结果,则必须再次编码.encode('latin1')为合适的编码(例如,如果您需要保留文字字节值;前256个Unicode代码点映射1对1).

您的示例实际上是带有转义的UTF-16数据.解码unicode_escape,返回以latin1保留字节,然后从utf-16-le(没有BOM的UTF 16小端)解码:

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\000@\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000'
>>> value.decode('unicode_escape').encode('latin1')  # convert to bytes
b's\x00u\x00p\x00p\x00o\x00r\x00t\x00@\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00'
>>> _.decode('utf-16-le') # decode from UTF-16-LE
'support@psiloc.com'
Run Code Online (Sandbox Code Playgroud)


Nat*_*ith 27

旧的"字符串转义"编解码器将字节串映射到字节串,并且关于如何处理此类编解码器存在很多争议,因此目前无法通过标准编码/解码接口使用它.

BUT,代码是仍然存在的C-API(如在PyBytes_En/DecodeEscape),并且这仍然经由无证暴露于的Python codecs.escape_encodecodecs.escape_decode.

>>> import codecs
>>> codecs.escape_decode(b"ab\\xff")
(b'ab\xff', 6)
>>> codecs.escape_encode(b"ab\xff")
(b'ab\\xff', 3)
Run Code Online (Sandbox Code Playgroud)

这些函数返回转换后的bytes对象,加上一个数字,表示处理了多少字节......你可以忽略后者.

>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\000@\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000'
>>> codecs.escape_decode(value)[0]
b's\x00u\x00p\x00p\x00o\x00r\x00t\x00@\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00'
Run Code Online (Sandbox Code Playgroud)

  • 依赖未记录的 API 是一个可怕的想法。永远不要在生产代码中这样做。 (2认同)

Mes*_*ion 21

如果你想str -to- str解码转义序列,那么输入和输出都是 Unicode:

def string_escape(s, encoding='utf-8'):
    return (s.encode('latin1')         # To bytes, required by 'unicode-escape'
             .decode('unicode-escape') # Perform the actual octal-escaping decode
             .encode('latin1')         # 1:1 mapping back to bytes
             .decode(encoding))        # Decode original encoding
Run Code Online (Sandbox Code Playgroud)

测试:

>>> string_escape('\\123omething special')
'Something special'

>>> string_escape(r's\000u\000p\000p\000o\000r\000t\000@'
                  r'\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000',
                  'utf-16-le')
'support@psiloc.com'
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您同意始终以 utf-8 结尾,则可以在单次往返中执行此操作,如下所示: `s.encode('latin1', 'backslashreplace').decode('unicode-escape')` - -- 参见 /sf/answers/4003481471/ (2认同)

Sér*_*gio 5

py2

"\\123omething special".decode('string-escape')
Run Code Online (Sandbox Code Playgroud)

py3

"\\123omething special".encode('utf-8').decode('unicode-escape')
Run Code Online (Sandbox Code Playgroud)