Проблема Python с неправильно сформированными строками, содержащими x
В какой-то момент наш скрипт python получает такую строку:
In [1]: ab = 'asdxeffective'
In [2]: print ab
asd�fectve \ \k\
Данные повреждены нам нужно escape x правильно интерпретировать как x, но c не имеет особого значения в строке, поэтому должен быть неповрежденным.
Пока что самое близкое решение, которое я нашел, это сделать что-то вроде:
In [1]: ab = 'asdxeffectve \ \\ \\\k\\\'
In [2]: print ab.encode('string-escape').replace('\\', '\').replace("\'", "'")
asdxeffectve \ \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 ответа:
'\\'
это то же самое, что'\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
Обратные косые черты вводят "escape-последовательности".
\x
специально позволяет указать байт, который задается в виде двух шестнадцатеричных цифр после x.ef
- это две шестнадцатеричные цифры, следовательно, вы не получите ошибки. Удвоьте обратную косую черту, чтобы избежать ее, или используйте необработанную строкуr"\xeffective"
.Edit: хотя консоль Python может показать вам
'\\'
, это является именно тем, что вы ожидаете. Вы просто говорите, что ожидаете чего-то другого, потому что путаете строку и ее представление. Это струна. содержит одну обратную косую черту. Если бы вы вывели его с помощьюНо строковый литерал
'\'
плохо сформирован (не закрыт, потому что\'
является Апострофом, а не обратной косой чертой и концом строкового литерала), поэтомуrepr
, который форматирует результаты в интерактивной оболочке, не производит его. Вместо этого он создает строковый литерал, который можно вставить в исходный код Python и получить тот же строковый объект. Например,len('\\') == 1
.
Escape-последовательность
\x
обозначает символ Юникода в строке, аef
интерпретируется как шестнадцатеричный код. Вы можете очистить строку, добавив дополнительный\
, или же сделать ее сырой строкой (r'\xeffective'
).>>> r'\xeffective'[0] '\\'
EDIT: вы можете преобразовать существующую строку, используя следующий хак:
>>> a = '\xeffective' >>> b = repr(a).strip("'") >>> b '\\xeffective'