我怎么在Python3 .decode(“字符串转义”)?(how do I .decode(

2019-07-19 17:43发布

我有一些逃脱了需要转义的字符串。 我想这样做在Python。

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

>>> "\\123omething special".decode('string-escape')
'Something special'
>>> 

如何做到这一点在Python3? 这不起作用:

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

我的目标是成为阿贝尔获得一个字符串是这样的:

s\000u\000p\000p\000o\000r\000t\000@\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000

并把它变成:

"support@psiloc.com"

我做的转换后,我就探头去看,如果我有字符串中的UTF-8或UTF-16进行编码。

Answer 1:

你将不得不使用unicode_escape代替:

>>> b"\\123omething special".decode('unicode_escape')

如果你开始str对象,而不是(相当于Python 2.7版的Unicode),您需要编码为字节先,然后用解码unicode_escape

如果需要字节最终的结果,就必须再次编码为一个合适的编码( .encode('latin1')例如,如果需要保留字面字节值;前256个Unicode码位映射1导通1)。

你举的例子实际上是UTF-16的数据与逃逸。 解码来自unicode_escape ,回latin1保存字节,然后从utf-16-le (UTF-16小端无BOM):

>>> 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'


Answer 2:

旧的“字符串转义”解码器映射到字节串字节串,并有不少关于如何处理这样的编解码器做辩论,所以它通过标准的编码/解码接口是当前不可用。

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)

这些函数返回转化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'


Answer 3:

不能使用unicode_escape上字节字符串(或者说,你可以,但它并不总是返回同样的事情string_escape做关于Python 2) -当心!

此函数实现string_escape使用正则表达式和定制替换逻辑。

def unescape(text):
    regex = re.compile(b'\\\\(\\\\|[0-7]{1,3}|x.[0-9a-f]?|[\'"abfnrt]|.|$)')
    def replace(m):
        b = m.group(1)
        if len(b) == 0:
            raise ValueError("Invalid character escape: '\\'.")
        i = b[0]
        if i == 120:
            v = int(b[1:], 16)
        elif 48 <= i <= 55:
            v = int(b, 8)
        elif i == 34: return b'"'
        elif i == 39: return b"'"
        elif i == 92: return b'\\'
        elif i == 97: return b'\a'
        elif i == 98: return b'\b'
        elif i == 102: return b'\f'
        elif i == 110: return b'\n'
        elif i == 114: return b'\r'
        elif i == 116: return b'\t'
        else:
            s = b.decode('ascii')
            raise UnicodeDecodeError(
                'stringescape', text, m.start(), m.end(), "Invalid escape: %r" % s
            )
        return bytes((v, ))
    result = regex.sub(replace, text)


文章来源: how do I .decode('string-escape') in Python3?