Come annullare l'escape di una stringa di escape con barra rovesciata?


101

Supponiamo che io abbia una stringa che è una versione con backslash di un'altra stringa. C'è un modo semplice, in Python, per annullare l'escape della stringa? Potrei, ad esempio, fare:

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

Tuttavia ciò comporta il passaggio di una stringa (possibilmente non attendibile) a eval () che è un rischio per la sicurezza. Esiste una funzione nella libreria standard che accetta una stringa e produce una stringa senza implicazioni per la sicurezza?

Risposte:


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

9
C'è qualcosa che è compatibile con Python 3?
thejinx0r

3
@ thejinx0r: dai un'occhiata qui: stackoverflow.com/questions/14820429/…
ChristopheD

30
Fondamentalmente per Python3 che vuoiprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD

3
Per Python 3, usavalue.encode('utf-8').decode('unicode_escape')
Casey Kuball

8
ATTENZIONE: value.encode('utf-8').decode('unicode_escape') danneggia i caratteri non ASCII nella stringa . A meno che non sia garantito che l'input contenga solo caratteri ASCII, questa non è una soluzione valida.
Alex Peters

35

Puoi usare quello ast.literal_evalche è sicuro:

Valuta in sicurezza un nodo espressione o una stringa contenente un'espressione Python. La stringa o il nodo fornito può essere costituito solo dalle seguenti strutture letterali Python: stringhe, numeri, tuple, elenchi, dict, booleani e Nessuno. (FINE)

Come questo:

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

3
La presenza di un punto e virgola di escape nella stringa interrompe questo codice. Genera un errore di sintassi "carattere imprevisto dopo carattere di continuazione di riga"
darksky

3
@darksky nota che la astlibreria richiede virgolette (o "o ', anche """o ''') attorno al tuo escaped_str, dal momento che sta effettivamente tentando di eseguirlo come codice Python ma migliora la sicurezza (impedisce l'iniezione di stringhe)
InQβ

@ no1xsyzy: Che nel caso dell'OP è già così; questa è la risposta corretta quando la strè una reprdi una stro bytesoggetto come nel caso del PO; la unicode-escaperisposta del codec è per quando non è a repr, ma qualche altra forma di testo con escape (non racchiuso tra virgolette come parte dei dati della stringa stessa).
ShadowRanger

con i caratteri utf-8 questo non funzionerà. controlla l'ultima risposta con il pacchetto di codici. funziona davvero.
rubmz

FWIW Stavo tentando di analizzare del testo JSON con escape e ho continuato a ricevere questo errore [ERROR] TypeError: string indices must be integerse questa soluzione ha funzionato per risolverlo. Elimina l'escape della stringa, quindi analizza come JSON.
cyber-monk il

20

Tutte le risposte fornite si interromperanno sulle stringhe Unicode generali. Quanto segue funziona per Python3 in tutti i casi, per quanto ne so:

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

Come delineato nei commenti, puoi anche utilizzare il literal_evalmetodo dal astmodulo in questo modo:

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

O come questo quando la tua stringa contiene davvero una stringa letterale (comprese le virgolette):

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

Tuttavia, se non si è sicuri se la stringa di input utilizza virgolette doppie o singole come delimitatori, o se non si può presumere che sia stato eseguito correttamente l'escape, è literal_evalpossibile che SyntaxErroril metodo di codifica / decodifica continui a funzionare.


ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"funziona bene per me con Python 3.7.3
oldrinb

Grazie per il commento @oldrinb! Ho modificato la risposta per includerla.
Jesko Hüttenhain

14

In python 3, gli stroggetti non hanno un decodemetodo e devi usare un bytesoggetto. La risposta di ChristopheD copre 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
Mettere insieme, value.encode('utf-8').decode('unicode_escape').
Casey Kuball

6
Questo purtroppo si interromperà se la stringa contiene alcuni caratteri non ASCII utf-8 (cioè caratteri polacchi)
Pax0r

Hai provato a scegliere una codifica adatta per il polacco nella chiamata a encode?
asac

con i caratteri utf-8 questo non funzionerà. controlla l'ultima risposta con il pacchetto di codici. funziona davvero.
rubmz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.