2012-10-11 12 views
2

在某些时候,我们的python脚本接收串那样:使用不正确格式化字符串Python的问题包含 X

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

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

数据被破坏,我们需要逃避\ x到正确解释为\ X,但\ c具有因此字符串中没有特殊含义,因此必须完好无损。

到目前为止,我发现的最接近的解决办法是做这样的事情:从IPython中采取

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

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

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

输出,我假设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 
+0

一个黑客是使用'repr',即'repr(s)[1:-1]'。 – DSM

+1

不直接调用'__repr__'。它拼写为'repr(ab)'。 – habnabit

+0

在字符串数据的源头修复这个问题更有意义。你能详细说明为什么你首先以ab ='asd \ xeffe \ ctive''的形式接收数据(而不是正确清理'ab ='asd \\ xeffe \\ ctive'')? – ezod

回答

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

\xhh是转义字符和\x被视为该逃逸开始

2

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

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

但字符串文字'\'是非法的构造(未关闭,因为\'是撇号,而不是一个反斜线和结束字串文本),所以repr,其格式在交互式外壳的结果,不产生它。相反,它会生成一个字符串文字,您可以将其粘贴到Python源代码中并获取相同的字符串对象。例如,len('\\') == 1

+1

我可能会误解,但我的印象是OP的字符串确实是'x ='\ xeffective'',问题是将它变回'y ='\\ xeffective''。 – DSM

+0

@DSM Huh,这个解释对我来说没有发生。可能的,但问题是*非常*模糊。在任何一种情况下,OP对字符串的表示形式及其价值都很困惑。 – delnan

1

\x转义序列表示字符串中的Unicode字符,并且ef被解释为十六进制代码。您可以通过添加额外的\来消毒字符串,或者使其成为原始字符串(r'\xeffective')。

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

编辑:你可以使用下面的技巧将现有的字符串:

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

好的,但如何将变量转换为'原始'变量。 r'\ xeffective'的作品,但如果ab ='\ xeffective'我该如何实现? – Drachenfels

+0

@Drachenfels:'r'''(“'raw'string”)仅适用于字符串*文字*,例如,在您的源代码中。记忆中没有这样的东西。请参阅[我的答案](http://stackoverflow.com/a/12844459/4279) – jfs

+1

''\ x''不*代表Unicode字符。 ''\ xef''是一个单字节(长度为1的字节串)。 'u'\ xef''是Unicode字符('u'\ u00ef''),例如在utf-8编码中它是2字节:'b'\ xc3 \ xaf'' – jfs