重新转义
在开始之前,先了解一下什么叫做“重新转义”。
本文中的“重新转义”,指的是对一串其内容可以转义的字符串,再一次进行转义,得到该字符串转义过后的新字符串。
举个例子:
# a的内容是一个反斜杠和一个n组合起来的字符串
a = '\\n'
# b与a的内容相同,使用了Python的防止转义语法使文本不转义
b = r'\n'
# 我们希望经过重新转义之后,把“反斜杠+字符”的组合转义成一个转义后的字符
真正的换行符 = 重新转义(a)
在此之前,我曾经使用做过类似的事情:
现在我将告诉大家,如何在 Python3 中做到同样的事情。
这个问题不简单
如果你用Google搜索这个问题,你可能会得到类似于这样的答案:
print '\\n'.decode('string-escape') # Python2
嗯,对于 Python2 ,这就是正确的做法。(233
如果你在 Python3 中尝试这么做,你会发现 str 类型是没有decode方法的。因为在 Python3 中, str 和 bytes 分离成两个不同的类型了[1]。而且 Python3 使用 Unicode 作为字符串内部编码。
你可能会这么想,既然 str 和 byte 分离了,如果把 str 类型转换成 bytes 类型,不就可以使用 decode 方法了吗?
于是写出这样的代码:
真正的换行符 = bytes('\\n', 'utf-8').decode('unicode-escape')
# 或者这么写
真正的换行符 = '\\n'.encode('utf-8').decode('unicode-escape')
print(真正的换行符)
然后你试了试,好像成功了。
其实没有成功,如果字符串里有中文(应该叫做非ASCII字符)……最后输出的结果里,全都是乱码。
也许你会通过一些奇怪的方式来实现二次转义,例如使用 eval() 函数。请别这么做,这样非常危险。
正确的做法
正确的做法是这样子的:
#! python3
import codecs
# 输出真正的换行符
print(codecs.escape_decode(bytes('\\n', 'utf-8'))[0].decode('utf-8'))
codecs.escape_decode 是一个 bytes 到 bytes 类型的转换器,它会把字符串转义一遍。
举一些例子:
- b'\\n' → b'\n'
- b'\\x00' → b'\x00'
这个方法不会考虑 bytes 内容是哪一种字符编码,或者不是字符编码。它只会转义 bytes 里的内容。
我们来总结一下:
import codecs
# Python 2
# 其实 Python2 不能用非 ASCII 字符作为标识符,这里仅供参考
def 重新转义(文本):
return 文本.decode('string-escape')
# Python 3
def 重新转义(文本):
return codecs.escape_decode(bytes(文本, 'utf-8'))[0].decode('utf-8')
嗯?你说……[0]是什么情况?
是这样的, escape_decode 返回一个Tuple,第一项为结果,第二项为字节数。
[1]: Python2 里,两者都是 str 类型,或者说 str 类型可以表示两者。
还有这种操作?
我正处在这个问题之中 看了博主的这个博文 竟然没看懂……
太感谢了 这个问题困扰了我很久 爱了