Wie entferne ich einen String mit Backslash-Escape?

100

Angenommen, ich habe eine Zeichenfolge, die eine Backslash-Escape-Version einer anderen Zeichenfolge ist. Gibt es in Python eine einfache Möglichkeit, die Zeichenfolge zu entfernen? Ich könnte zum Beispiel tun:

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

Dies beinhaltet jedoch die Übergabe einer (möglicherweise nicht vertrauenswürdigen) Zeichenfolge an eval (), was ein Sicherheitsrisiko darstellt. Gibt es eine Funktion in der Standardbibliothek, die eine Zeichenfolge verwendet und eine Zeichenfolge ohne Auswirkungen auf die Sicherheit erzeugt?

Nick
quelle

Antworten:

137
>>> print '"Hello,\\nworld!"'.decode('string_escape')
"Hello,
world!"
ChristopheD
quelle
9
Gibt es etwas, das mit Python 3 kompatibel ist?
thejinx0r
3
@ thejinx0r: Schauen Sie hier vorbei: stackoverflow.com/questions/14820429/…
ChristopheD
29
Grundsätzlich für Python3 möchten Sieprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD
3
Verwenden Sie für Python 3value.encode('utf-8').decode('unicode_escape')
Casey Kuball
8
WARNUNG: value.encode('utf-8').decode('unicode_escape') Beschädigt Nicht-ASCII-Zeichen in der Zeichenfolge . Dies ist keine gültige Lösung, es sei denn, die Eingabe enthält garantiert nur ASCII-Zeichen.
Alex Peters
34

Sie können verwenden, ast.literal_evalwas sicher ist:

Bewerten Sie sicher einen Ausdrucksknoten oder eine Zeichenfolge, die einen Python-Ausdruck enthält. Die angegebene Zeichenfolge oder der angegebene Knoten besteht möglicherweise nur aus den folgenden Python-Literalstrukturen: Zeichenfolgen, Zahlen, Tupel, Listen, Diktate, Boolesche Werte und Keine. (ENDE)

So was:

>>> import ast
>>> escaped_str = '"Hello,\\nworld!"'
>>> print ast.literal_eval(escaped_str)
Hello,
world!
Nathanismus
quelle
3
Ein Escape-Semikolon in der Zeichenfolge unterbricht diesen Code. Wirft einen Syntaxfehler "unerwartetes Zeichen nach
Zeilenfortsetzungszeichen
3
@darksky Beachten Sie, dass für die astBibliothek Anführungszeichen (entweder "oder ', sogar """oder ''') um Ihren Escape_str erforderlich sind, da sie tatsächlich versucht, sie als Python-Code auszuführen, aber die Sicherheit erhöht (verhindert das
Einfügen von
@ no1xsyzy: Was im Fall des OP bereits der Fall ist; dies ist die richtige Antwort , wenn der streine ist reprvon einem stroder bytesObjekt wie in dem OP des Fall; Die unicode-escapeCodec-Antwort ist für den Fall, dass es sich nicht um eine repr, sondern um eine andere Form von maskiertem Text handelt (nicht als Anführungszeichen als Teil der Zeichenfolgendaten selbst umgeben).
ShadowRanger
Mit utf-8 Zeichen funktioniert dies nicht. Überprüfen Sie die letzte Antwort mit Code-Paket. es funktioniert tatsächlich.
Rubmz
20

Alle gegebenen Antworten werden bei allgemeinen Unicode-Zeichenfolgen unterbrochen. Folgendes funktioniert in allen Fällen für Python3, soweit ich das beurteilen kann:

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

Wie in den Kommentaren beschrieben, können Sie die literal_evalMethode aus dem astModul auch folgendermaßen verwenden :

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

Oder so, wenn Ihre Zeichenfolge wirklich ein Zeichenfolgenliteral enthält (einschließlich der Anführungszeichen):

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

Wenn Sie sich jedoch nicht sicher sind, ob die Eingabezeichenfolge doppelte oder einfache Anführungszeichen als Trennzeichen verwendet oder wenn Sie nicht davon ausgehen können, dass sie überhaupt ordnungsgemäß maskiert wird, literal_evalkann es sein, dass SyntaxErrordie Codierungs- / Decodierungsmethode noch eine Weile funktioniert.

Jesko Hüttenhain
quelle
ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"funktioniert gut für mich mit Python 3.7.3
oldrinb
Danke für den Kommentar @oldrinb! Ich habe die Antwort so bearbeitet, dass sie das enthält.
Jesko Hüttenhain
14

In Python 3 haben strObjekte keine decodeMethode und Sie müssen ein bytesObjekt verwenden. Die Antwort von ChristopheD bezieht sich auf 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"
asac
quelle
2
Zusammensetzen , value.encode('utf-8').decode('unicode_escape').
Casey Kuball
6
Dies wird leider brechen, wenn die Zeichenfolge einige utf-8 Nicht-ASCII-Zeichen (dh polnische Zeichen) enthält
Pax0r
Haben Sie versucht, im Anruf eine Codierung auszuwählen, die für das Polieren geeignet ist encode?
Asac
Mit utf-8 Zeichen funktioniert dies nicht. Überprüfen Sie die letzte Antwort mit Code-Paket. es funktioniert tatsächlich.
Rubmz