包含\ x的格式不正确的字符串的Python问题

时间:2012-10-11 16:07:27

标签: python string unicode bytestring

在某些时候,我们的python脚本会收到类似的字符串:

In [1]: ab = 'asd\xeffe\ctive'

In [2]: print ab
asd�fe\ctve \ \\ \\\k\\\

数据损坏我们需要转义\ x才能正确解释为\ x但\ c在字符串中没有特殊含义因此必须完好无损。

到目前为止,我找到的最接近的解决方案是:

In [1]: ab = 'asd\xeffe\ctve \\ \\\\ \\\\\\k\\\\\\'

In [2]: print ab.encode('string-escape').replace('\\\\', '\\').replace("\\'", "'")

asd\xeffe\ctve \ \\ \\\k\\\

从IPython中获取的输出,我假设ab是一个字符串而不是unicode字符串(在后面的例子中,我们必须做类似的事情:

def escape_string(s):
    if isinstance(s, str):
        s = s.encode('string-escape').replace('\\\\', '\\').replace("\\'", "'")
    elif isinstance(s, unicode):
        s = s.encode('unicode-escape').replace('\\\\', '\\').replace("\\'", "'")
    return s

4 个答案:

答案 0 :(得分:3)

\xhh是一个转义字符,\x被视为此转义的开始。

答案 1 :(得分:2)

反斜杠引入了“转义序列”。 \x特别允许您指定一个字节,该字节在x之后以两个十六进制数字给出。 ef是两个十六进制数字,因此您没有错误。将反斜杠加倍以使其转义,或使用原始字符串r"\xeffective"

编辑:虽然Python控制台可能会向您显示'\\',但 正是您所期望的。你只是说你期待别的东西,因为你混淆了字符串及其表示。它是一个包含单个反斜杠的字符串。如果你用print输出它,你会看到一个反斜杠。

但字符串文字'\'格式不正确(未关闭,因为\'是撇号,而不是反斜杠和字符串结尾 - 文字),所以repr,在交互式shell上格式化结果,不生成它。相反,它会生成一个字符串文字,您可以将其粘贴到Python源代码中并获取相同的字符串对象。例如,len('\\') == 1

答案 2 :(得分:2)

'\\''\x5c'相同。将反斜杠字符编写为 Python字符串文字只是两种不同的方法。

这些文字字符串:r'\c''\\c''\x5cc''\x5c\x63'在内存中是相同的 str个对象。

'\xef'是一个字节(239作为整数),但r'\xef'(与'\\xef'相同)是一个4字节的字符串:'\x5c\x78\x65\x66'

如果s[0]返回'\xef',那么它就是s对象实际包含的内容。如果错了,那么修复数据来源。


注意:string-escape也会转义\n之类的内容:

>>> print u'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''.encode('unicode-escape')
\xef\\c\\\u2603"'\u2603\u2603"'\n\xa0
>>> print b'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''.encode('string-escape')
\xef\\c\\\\N{SNOWMAN}"\'\xe2\x98\x83\\u2603"\'\n\xa0

backslashreplace仅用于导致UnicodeEncodeError的字符:

>>> print u'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''
ï\c\☃"'☃☃"'

>>> print b'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''
�\c\\N{SNOWMAN}"'☃\u2603"'
�
>>> print u'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''.encode('ascii', 'backslashreplace')
\xef\c\\u2603"'\u2603\u2603"'
\xa0
>>> print b'''\xef\c\\\N{SNOWMAN}"'\
... ☃\u2603\"\'\n\xa0'''.decode('latin1').encode('ascii', 'backslashreplace')
\xef\c\\N{SNOWMAN}"'\xe2\x98\x83\u2603"'
\xa0

答案 3 :(得分:1)

\x转义序列表示字符串中的Unicode字符,ef被解释为十六进制代码。您可以通过添加其他\来清理字符串,或者将其设为原始字符串(r'\xeffective')。

>>> r'\xeffective'[0]
'\\'

编辑:您可以使用以下hack转换现有字符串:

>>> a = '\xeffective'
>>> b = repr(a).strip("'")
>>> b
'\\xeffective'