Як відмовитися від рядка, що вийшов з косої риски?


100

Припустимо, у мене є рядок, яка є зворотно-косою версією іншої рядки. Чи існує простий спосіб у Python відрізати рядок? Я міг би, наприклад, зробити:

>>> escaped_str = '"Hello,\\nworld!"'
>>> raw_str = eval(escaped_str)
>>> print raw_str
Hello,
world!
>>> 

Однак це передбачає передачу (можливо, ненадійного) рядка в eval (), що є ризиком для безпеки. Чи є в стандартній lib функція, яка бере рядок і створює рядок без наслідків для безпеки?

Відповіді:


137
>>> print '"Hello,\\nworld!"'.decode('string_escape')
"Hello,
world!"

9
Чи є щось сумісне з python 3?
thejinx0r

3
@ thejinx0r: подивіться тут: stackoverflow.com/questions/14820429/…
ChristopheD

29
В основному для Python3 ви хочетеprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD

3
Для python 3 використовуйтеvalue.encode('utf-8').decode('unicode_escape')
Casey Kuball

8
УВАГА: value.encode('utf-8').decode('unicode_escape') пошкоджує символи, що не належать до ASCII . Якщо вхід не гарантує лише символи ASCII, це не є дійсним рішенням.
Алекс Петерс

35

Ви можете використовувати ast.literal_evalбезпечний:

Безпечно оцініть вузол виразу або рядок, що містить вираз Python. Наданий рядок або вузол може складатися лише з таких буквальних структур Python: рядки, числа, кортежі, списки, дикти, булеві та None. (END)

Подобається це:

>>> import ast
>>> escaped_str = '"Hello,\\nworld!"'
>>> print ast.literal_eval(escaped_str)
Hello,
world!

3
Забезпеченість напів двокрапкою в рядку порушує цей код. Викидає синтаксичну помилку "несподіваний символ після продовження рядка"
темний

3
@darksky зауважив, що astбібліотеці потрібні лапки (або "або ', навіть, """або ''') навколо вашого escape_str, оскільки він насправді намагається запустити його як код Python, але підвищує безпеку (запобігає введенню рядків)
InQβ

@ no1xsyzy: що вже є у справі ОП; це правильна відповідь, коли strє reprоб'єкт strабо bytesоб'єкт, як у випадку з ОП; відповідь unicode-escapeкодека призначена для тих reprвипадків, коли це не а , а якась інша форма втеченого тексту (не оточена цитатами як частина самих рядкових даних).
ShadowRanger

з utf-8 знаками це не вийде. оформити останню відповідь з пакетом кодів. це насправді працює.
rubmz

FWIW Я намагався проаналізувати якийсь уникнутий текст JSON і продовжував отримувати цю помилку, [ERROR] TypeError: string indices must be integersі це рішення працювало на її вирішенні. Знімайте рядок, а потім розбирайте як JSON.
кібермонах

20

Усі відповіді будуть розбиті на загальні рядки Unicode. Настільки, наскільки я можу, для Python3 працює у всіх випадках.

from codecs import encode, decode
sample = u'mon€y\\nröcks'
result = decode(encode(sample, 'latin-1', 'backslashreplace'), 'unicode-escape')
print(result)

Як зазначено в коментарях, ви також можете використовувати literal_evalметод з astмодуля так:

import ast
sample = u'mon€y\\nröcks'
print(ast.literal_eval(F'"{sample}"'))

Або так, коли ваша рядок дійсно містить літеральний рядок (включаючи лапки):

import ast
sample = u'"mon€y\\nröcks"'
print(ast.literal_eval(sample))

Однак якщо ви не впевнені в тому, що вхідна рядок використовує подвійні чи одиничні лапки як роздільники, або коли ви не можете припустити, що вона взагалі належним чином скасується, тоді literal_evalможе виникнути деякий SyntaxErrorчас, коли метод кодування / декодування все ще буде працювати.


ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"добре працює для мене з Python 3.7.3
oldrinb

Дякуємо за коментар @oldrinb! Я відредагував відповідь, щоб включити її.
Jesko Hüttenhain

14

У python 3 в strоб'єктах немає decodeметоду, і ви повинні використовувати bytesоб'єкт. Відповідь ChristopheD охоплює python 2.

# create a `bytes` object from a `str`
my_str = "Hello,\\nworld"
# (pick an encoding suitable for your str, e.g. 'latin1')
my_bytes = my_str.encode("utf-8")

# or directly
my_bytes = b"Hello,\\nworld"

print(my_bytes.decode("unicode_escape"))
# "Hello,
# world"

2
Збираємо разом value.encode('utf-8').decode('unicode_escape').
Кейсі Кубалл

6
Це, на жаль, розірветься, якщо рядок містить кілька символів utf-8, які не є ascii (тобто польські символи)
Pax0r

Ви спробували вибрати кодування, яке підходить для польської мови під час заклику до encode?
asac

з utf-8 знаками це не вийде. оформити останню відповідь з пакетом кодів. це насправді працює.
rubmz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.