Иногда, когда я получаю ввод от файла или пользователя, я получаю строку с escape-последовательностями в ней. Я хотел бы обрабатывать escape-последовательности так же, как Python обрабатывает escape-последовательности в строковых литералах .
Например, допустим, myString
определяется как:
>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs
Мне нужна функция (я ее назову process
), которая делает это:
>>> print(process(myString))
spam
eggs
Важно, чтобы функция могла обрабатывать все escape-последовательности в Python (перечисленные в таблице по ссылке выше).
Есть ли у Python функция для этого?
'spam'+"eggs"+'''some'''+"""more"""
будет обработана?myString = "'spam'+\"eggs\"+'''some'''+\"\"\"more\"\"\""
,print(bytes(myString, "utf-8").decode("unicode_escape"))
вроде работает.Ответы:
Правильнее всего использовать код «escape-последовательность» для декодирования строки.
Не используйте AST или eval. Использование строковых кодеков намного безопаснее.
источник
'string\W+escape'
Notice that spelling alternatives that only differ in case or use a hyphen instead of an underscore are also valid aliases; therefore, e.g. 'utf-8' is a valid alias for the 'utf_8' codec.
>>> print("juancarlo\\tañez".encode('utf-8').decode('unicode_escape'))
Вы получите:juancarlo añez
latin1
предполагаетсяunicode_escape
, повторить бит кодирования / декодирования, напримерs.encode('utf-8').decode('unicode_escape').encode('latin1').decode('utf8')
unicode_escape
не работает вообщеОказывается, решение
string_escape
илиunicode_escape
вообще не работает - в частности, не работает при наличии действительного Unicode.Если вы можете быть уверены, что каждый символ, не являющийся символом ASCII, будет экранирован (и помните, что все, что выходит за пределы первых 128 символов, не является символом ASCII), все
unicode_escape
будет правильно для вас. Но если в вашей строке уже есть какие-либо буквальные символы, отличные от ASCII, все пойдет не так.unicode_escape
в основном предназначен для преобразования байтов в текст Unicode. Но во многих местах - например, в исходном коде Python - исходные данные уже являются текстом Unicode.Единственный способ, которым это может работать правильно, - это сначала кодировать текст в байты. UTF-8 - разумная кодировка для всего текста, так что она должна работать, верно?
Следующие примеры относятся к Python 3, поэтому строковые литералы чище, но та же проблема существует с немного разными проявлениями как на Python 2, так и на 3.
Что ж, это неправильно.
Новый рекомендуемый способ использования кодеков, декодирующих текст в текст, - это
codecs.decode
прямой вызов . Это помогает?Не за что. (Кроме того, это UnicodeError на Python 2.)
unicode_escape
Кодек, несмотря на свое название, оказывается, предположить , что все не-ASCII байты в кодировке Latin-1 (ISO-8859-1). Итак, вам нужно будет сделать это так:Но это ужасно. Это ограничивает вас 256 символами Latin-1, как будто Unicode никогда не был изобретен!
Добавление регулярного выражения для решения проблемы
(Удивительно, но сейчас у нас нет двух проблем.)
Что нам нужно сделать, так это применить
unicode_escape
декодер только к тем вещам, которые, несомненно, являются текстом ASCII. В частности, мы можем убедиться, что применили его только к допустимым escape-последовательностям Python, которые гарантированно являются текстом ASCII.План таков: мы найдем escape-последовательности с помощью регулярного выражения и используем функцию в качестве аргумента для
re.sub
чтобы заменить их неэкранированным значением.И с этим:
источник
os.sep
вообще работает? Я пытаюсь это сделать:patt = '^' + self.prefix + os.sep ; name = sub(decode_escapes(patt), '', name)
а не получается. Вместо новой строки стоит точка с запятой.os.sep
есть?) Если у вас есть escape-последовательности с обратной косой чертой в именах каталогов Windows, ситуацию практически невозможно исправить.Фактически правильный и удобный ответ для python 3:
Подробности относительно
codecs.escape_decode
:codecs.escape_decode
это байтовый декодерcodecs.escape_decode
декодирует escape-последовательности ascii, такие как:b"\\n"
->b"\n"
,b"\\xce"
->b"\xce"
.codecs.escape_decode
не заботится или не должен знать о кодировке байтового объекта, но кодировка экранированных байтов должна соответствовать кодировке остальной части объекта.Задний план:
unicode_escape
это неправильное решение для python3. Это связано с тем, чтоunicode_escape
декодирует экранированные байты, а затем декодирует байты в строку Unicode, но не получает никакой информации о том, какой кодек использовать для второй операции.codecs.escape_decode
Из этого ответа я впервые обнаружил, что «как мне .decode ('string-escape') в Python3?» . Как говорится в этом ответе, эта функция в настоящее время не задокументирована для python 3.источник
\x
байтов UTF-8. Но поскольку он декодирует байты в байты, он не может - и не может - декодировать любые escape-символы Unicode, отличные от ASCII, такие как\u
escape -символы .В
ast.literal_eval
Функция приближается, но он будет ожидать , что строка , которая будет цитироваться первым.Конечно, интерпретация Python экранирования обратной косой черты зависит от того, как заключена строка в кавычки (
""
vsr""
vsu""
, тройные кавычки и т. Д.), Поэтому вы можете заключить пользовательский ввод в подходящие кавычки и перейти кliteral_eval
. Заключение в кавычки также предотвратитliteral_eval
возврат числа, кортежа, словаря и т. Д.Все еще может стать сложным, если пользователь вводит кавычки без кавычек того типа, который вы собираетесь обернуть вокруг строки.
источник
myString = "\"\ndoBadStuff()\n\""
,print(ast.literal_eval('"' + myString + '"'))
кажется, пытаются кода выполнения. Чемast.literal_eval
отличается / безопаснее чемeval
?literal_eval
никогда не выполняет код. Из документации: «Это можно использовать для безопасной оценки строк, содержащих выражения Python, из ненадежных источников без необходимости самостоятельно разбирать значения».Это плохой способ сделать это, но он сработал для меня, когда я пытался интерпретировать экранированные восьмеричные числа, переданные в строковом аргументе.
Стоит упомянуть, что существует разница между eval и ast.literal_eval (eval гораздо опаснее). См. Использование функции eval () в python и ast.literal_eval ()?
источник
Код ниже должен работать, если \ n требуется для отображения в строке.
источник
replace
ничего не делает), использует сильно устаревшие API (string
функции модуля такого рода устарели в Python 2.0, замененыstr
методами и полностью исчезли в Python 3), и только обрабатывает конкретный случай замены одной новой строки, а не общую обработку escape.