Como cancelar o escape de uma string com escape de barra invertida?


100

Suponha que eu tenha uma string que é uma versão com escape de barra invertida de outra string. Existe uma maneira fácil, em Python, de desfazer a fuga da string? Eu poderia, por exemplo, fazer:

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

No entanto, isso envolve passar uma string (possivelmente não confiável) para eval (), o que é um risco de segurança. Existe uma função no lib padrão que pega uma string e produz uma string sem implicações de segurança?

Respostas:


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

9
Existe algo que seja compatível com o python 3?
thejinx0r

3
@ thejinx0r: dê uma olhada aqui: stackoverflow.com/questions/14820429/…
ChristopheD

29
Basicamente para Python3 que você desejaprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD,

3
Para python 3, usevalue.encode('utf-8').decode('unicode_escape')
Casey Kuball

8
AVISO: value.encode('utf-8').decode('unicode_escape') corrompe caracteres não ASCII na string . A menos que seja garantido que a entrada contenha apenas caracteres ASCII, esta não é uma solução válida.
Alex Peters

34

Você pode usar o ast.literal_evalque é seguro:

Avalie com segurança um nó de expressão ou uma string contendo uma expressão Python. A string ou nó fornecido pode consistir apenas nas seguintes estruturas literais do Python: strings, números, tuplas, listas, dicts, booleanos e nenhum. (FIM)

Como isso:

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

3
Ter um ponto-e-vírgula de escape na string quebra esse código. Lança um erro de sintaxe "caractere inesperado após caractere de continuação de linha"
darksky 01 de

3
@darksky observe que a astbiblioteca requer aspas ( "ou ', mesmo """ou ''') em torno de seu escaped_str, uma vez que está realmente tentando executá-lo como código Python, mas aumenta a segurança (evita injeção de string)
InQβ

@ no1xsyzy: O que no caso do OP já é o caso; esta é a resposta correta quando o stré a reprde a strou um bytesobjeto como no caso do OP; a unicode-escaperesposta do codec é para quando não é um repr, mas alguma outra forma de texto de escape (não entre aspas como parte dos próprios dados da string).
ShadowRanger

com caracteres utf-8 isso não funcionará. verifique a última resposta com pacote de códigos. realmente funciona.
rubmz

20

Todas as respostas fornecidas serão interrompidas em strings Unicode gerais. O seguinte funciona para Python3 em todos os casos, tanto quanto posso dizer:

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

Conforme descrito nos comentários, você também pode usar o literal_evalmétodo do astmódulo assim:

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

Ou assim, quando sua string realmente contém um literal de string (incluindo as aspas):

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

No entanto, se você não tiver certeza se a string de entrada usa aspas duplas ou simples como delimitadores, ou quando você não pode presumir que ela tenha um escape adequado, literal_evalpode demorar um SyntaxErrorpouco para que o método de codificação / decodificação ainda funcione.


ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"funciona bem para mim com Python 3.7.3
oldrinb

Obrigado pelo comentário @oldrinb! Eu editei a resposta para incluir isso.
Jesko Hüttenhain

14

No python 3, os strobjetos não têm um decodemétodo e você deve usar um bytesobjeto. A resposta de ChristopheD cobre 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
Juntando tudo value.encode('utf-8').decode('unicode_escape'),.
Casey Kuball

6
Infelizmente, isso será interrompido se a string contiver alguns caracteres não-ascii utf-8 (ou seja, caracteres
polidos

Você já tentou escolher uma codificação adequada para polimento na chamada para encode?
asac

com caracteres utf-8 isso não funcionará. verifique a última resposta com pacote de códigos. realmente funciona.
rubmz
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.