Wenn ich Eingaben von einer Datei oder vom Benutzer erhalte, erhalte ich manchmal eine Zeichenfolge mit Escape-Sequenzen. Ich möchte die Escape-Sequenzen genauso verarbeiten wie Python Escape-Sequenzen in String-Literalen .
Angenommen, es myString
ist definiert als:
>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs
Ich möchte eine Funktion (ich werde sie nennen process
), die dies tut:
>>> print(process(myString))
spam
eggs
Es ist wichtig, dass die Funktion alle Escape-Sequenzen in Python verarbeiten kann (in einer Tabelle im obigen Link aufgeführt).
Hat Python eine Funktion, um dies zu tun?
'spam'+"eggs"+'''some'''+"""more"""
verarbeitet wird?myString = "'spam'+\"eggs\"+'''some'''+\"\"\"more\"\"\""
,print(bytes(myString, "utf-8").decode("unicode_escape"))
Scheint zu funktionieren.Antworten:
Das Richtige ist, den 'String-Escape'-Code zu verwenden, um den String zu dekodieren.
Verwenden Sie nicht den AST oder die Bewertung. Die Verwendung der String-Codecs ist viel sicherer.
quelle
'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'))
Sie erhalten:juancarlo añez
latin1
angenommen wirdunicode_escape
, wiederholen Sie das Codierungs- / Decodierungsbit, z. B.s.encode('utf-8').decode('unicode_escape').encode('latin1').decode('utf8')
unicode_escape
funktioniert im Allgemeinen nichtEs stellt sich heraus, dass die Lösung
string_escape
oderunicode_escape
im Allgemeinen nicht funktioniert - insbesondere nicht , wenn tatsächlich Unicode vorhanden ist.Wenn Sie sicher sein können, dass jedes Nicht-ASCII-Zeichen maskiert wird (und denken Sie daran, dass alles, was über die ersten 128 Zeichen hinausgeht, kein ASCII-Zeichen ist),
unicode_escape
wird dies das Richtige für Sie tun. Wenn Ihre Zeichenfolge jedoch bereits wörtliche Nicht-ASCII-Zeichen enthält, wird ein Fehler auftreten.unicode_escape
ist grundsätzlich darauf ausgelegt, Bytes in Unicode-Text umzuwandeln. Aber an vielen Stellen - zum Beispiel im Python-Quellcode - sind die Quelldaten bereits Unicode-Text.Dies kann nur dann richtig funktionieren, wenn Sie den Text zuerst in Bytes codieren. UTF-8 ist die sinnvolle Codierung für den gesamten Text, damit das funktioniert, oder?
Die folgenden Beispiele befinden sich in Python 3, sodass die Zeichenfolgenliterale sauberer sind. Das gleiche Problem besteht jedoch bei leicht unterschiedlichen Erscheinungsformen in Python 2 und 3.
Nun, das ist falsch.
Die neue empfohlene Methode zur Verwendung von Codecs, die Text in Text dekodieren, besteht darin,
codecs.decode
direkt aufzurufen . Hilft das?Überhaupt nicht. (Außerdem ist das Obige ein UnicodeError unter Python 2.)
Der
unicode_escape
Codec geht trotz seines Namens davon aus, dass alle Nicht-ASCII-Bytes in der Latin-1-Codierung (ISO-8859-1) vorliegen. Sie müssten es also so machen:Aber das ist schrecklich. Dies beschränkt Sie auf die 256 Latin-1-Zeichen, als wäre Unicode überhaupt nicht erfunden worden!
Hinzufügen eines regulären Ausdrucks zur Lösung des Problems
(Überraschenderweise haben wir jetzt keine zwei Probleme.)
Was wir tun müssen, ist, den
unicode_escape
Decoder nur auf Dinge anzuwenden , von denen wir sicher sind, dass sie ASCII-Text sind. Insbesondere können wir sicherstellen, dass es nur auf gültige Python-Escape-Sequenzen angewendet wird, bei denen es sich garantiert um ASCII-Text handelt.Der Plan ist, Escape-Sequenzen mit einem regulären Ausdruck zu finden und eine Funktion als Argument zu verwenden
re.sub
, um sie durch ihren nicht entkoppelten Wert zu ersetzen.Und damit:
quelle
os.sep
überhaupt? Ich versuche das:patt = '^' + self.prefix + os.sep ; name = sub(decode_escapes(patt), '', name)
und es funktioniert nicht. Semikolon ist dort anstelle einer neuen Zeile.os.sep
sind?) Wenn Sie in Ihren Windows-Verzeichnisnamen umgekehrte Escape-Sequenzen verwendet haben, ist die Situation so gut wie nicht behebbar.Die eigentlich richtige und bequeme Antwort für Python 3:
Details zu
codecs.escape_decode
:codecs.escape_decode
ist ein Byte-zu-Byte-Decodercodecs.escape_decode
decodiert ASCII-Escape-Sequenzen wie:b"\\n"
->b"\n"
,b"\\xce"
->b"\xce"
.codecs.escape_decode
kümmert sich nicht um die Codierung des Byte-Objekts oder muss diese kennen, aber die Codierung der maskierten Bytes sollte mit der Codierung des restlichen Objekts übereinstimmen.Hintergrund:
unicode_escape
ist die falsche Lösung für Python3. Dies liegt daran, dassunicode_escape
dekodierte Bytes decodiert und dann Bytes in Unicode-Zeichenfolgen decodiert werden, aber keine Informationen darüber erhalten, welcher Codec für die zweite Operation verwendet werden soll.codecs.escape_decode
aus dieser Antwort: "Wie kann ich .decode ('string-Escape') in Python3?" . Wie in dieser Antwort angegeben, ist diese Funktion derzeit für Python 3 nicht dokumentiert.quelle
\x
Zeichen von UTF-8-Bytes sind. Da es jedoch Bytes in Bytes dekodiert, kann und kann es keine Escapezeichen von Nicht-ASCII-Unicode-Zeichen wie\u
Escapezeichen dekodieren .Die
ast.literal_eval
Funktion kommt nahe, aber es wird erwartet, dass die Zeichenfolge zuerst richtig in Anführungszeichen gesetzt wird.Natürlich hängt Pythons Interpretation von Backslash-Escapezeichen davon ab, wie die Zeichenfolge in Anführungszeichen gesetzt wird (
""
vsr""
vsu""
, dreifache Anführungszeichen usw.). Daher möchten Sie möglicherweise die Benutzereingaben in geeignete Anführungszeichen setzen und an übergebenliteral_eval
. Wenn Sie es in Anführungszeichen setzen, wird auch verhindertliteral_eval
, dass eine Zahl, ein Tupel, ein Wörterbuch usw. zurückgegeben werden.Es kann immer noch schwierig werden, wenn der Benutzer nicht zitierte Anführungszeichen des Typs eingibt, den Sie um die Zeichenfolge wickeln möchten.
quelle
myString = "\"\ndoBadStuff()\n\""
,print(ast.literal_eval('"' + myString + '"'))
scheint zu laufen Code zu versuchen. Wie istast.literal_eval
etwas anders / sicherer alseval
?literal_eval
führt niemals Code aus. In der Dokumentation heißt es: "Dies kann zum sicheren Auswerten von Zeichenfolgen verwendet werden, die Python-Ausdrücke aus nicht vertrauenswürdigen Quellen enthalten, ohne dass die Werte selbst analysiert werden müssen."Dies ist eine schlechte Methode, aber es hat bei mir funktioniert, als ich versucht habe, maskierte Oktale zu interpretieren, die in einem String-Argument übergeben wurden.
Es ist erwähnenswert, dass es einen Unterschied zwischen eval und ast.literal_eval gibt (eval ist viel unsicherer). Siehe Verwenden von pythons eval () vs. ast.literal_eval ()?
quelle
Der folgende Code sollte funktionieren für \ n muss in der Zeichenfolge angezeigt werden.
quelle
replace
nichts), verwendet stark veraltete APIs (diestring
Modulfunktionen dieser Art sind ab Python 2.0 veraltet, werden durch diestr
Methoden ersetzt und sind in Python 3 vollständig verschwunden) und nur behandelt den speziellen Fall des Ersetzens einer einzelnen neuen Zeile, nicht die allgemeine Escape-Verarbeitung.