2012-10-11 13 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