我如何.decode('string转义')在Python3?
我有一些逃避的string需要非转义。 我想用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 >>>
我的目标是成为一个像这样的string:
s\000u\000p\000p\000o\000r\000t\000@\000p\000s\000i\000l\000o\000c\000.\000c\000o\000m\000
把它变成:
"support@psiloc.com"
在完成转换之后,我们将探究我的string是否以UTF-8或UTF-16编码。
你将不得不使用unicode_escape
代替:
>>> b"\\123omething special".decode('unicode_escape')
如果你从一个str
对象开始 (相当于python 2.7 unicode),你需要首先编码字节,然后用unicode_escape
解码。
如果你需要字节作为最终结果,你将不得不再次编码到一个合适的编码( .encode('latin1')
,如果你需要保留文字字节值;前255个unicode代码点映射1-on- 1)。
你的例子实际上是带有转义的UTF-16数据。 从unicode_escape
解码,返回到latin1
以保留字节,然后从utf-16-le
(UTF 16小端没有BOM)中unicode_escape
:
>>> 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'
旧的“string转义(string-escape)”编解码器将字节串映射为字节串,并且对于如何使用这种编解码器存在很多争议,所以目前通过标准的编码/解码接口是不可用的。
但是,代码仍然存在于C-API(如PyBytes_En/DecodeEscape
)中,并且仍然通过未codecs.escape_encode
和codecs.escape_decode
向Python codecs.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
对象,加上一个数字表示处理了多less字节……你可以忽略后者。
>>> 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'
你不能在字节string上使用unicode_escape
(或者说,你可以,但是并不总是返回与Python 2中的string_escape
相同的东西) – 小心!
该函数使用正则expression式和自定义replace逻辑来实现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)