Parfois, lorsque j'obtiens une entrée d'un fichier ou de l'utilisateur, j'obtiens une chaîne avec des séquences d'échappement. Je voudrais traiter les séquences d'échappement de la même manière que Python traite les séquences d'échappement dans les littéraux de chaîne .
Par exemple, disons qu'il myString
est défini comme:
>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs
Je veux une fonction (je l'appellerai process
) qui fait ceci:
>>> print(process(myString))
spam
eggs
Il est important que la fonction puisse traiter toutes les séquences d'échappement en Python (répertoriées dans un tableau dans le lien ci-dessus).
Python a-t-il une fonction pour faire cela?
'spam'+"eggs"+'''some'''+"""more"""
soit traitée?myString = "'spam'+\"eggs\"+'''some'''+\"\"\"more\"\"\""
,print(bytes(myString, "utf-8").decode("unicode_escape"))
semble fonctionner.Réponses:
La bonne chose à faire est d'utiliser le code 'string-escape' pour décoder la chaîne.
N'utilisez pas AST ou eval. L'utilisation des codecs de chaîne est beaucoup plus sûre.
la source
'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'))
Vous obtenez:juancarlo añez
latin1
est supposé parunicode_escape
, refaire le bit d'encodage / décodage, par exemples.encode('utf-8').decode('unicode_escape').encode('latin1').decode('utf8')
unicode_escape
ne fonctionne pas en généralIl s'avère que la solution
string_escape
ouunicode_escape
ne fonctionne pas en général - en particulier, elle ne fonctionne pas en présence d'Unicode réel.Si vous pouvez être sûr que chaque caractère non ASCII sera échappé (et rappelez-vous que tout ce qui dépasse les 128 premiers caractères n'est pas ASCII),
unicode_escape
fera ce qu'il faut pour vous. Mais s'il y a déjà des caractères littéraux non ASCII dans votre chaîne, les choses iront mal.unicode_escape
est fondamentalement conçu pour convertir des octets en texte Unicode. Mais dans de nombreux endroits - par exemple, le code source Python - les données source sont déjà du texte Unicode.La seule façon dont cela peut fonctionner correctement est de coder d'abord le texte en octets. UTF-8 est le codage sensé pour tout le texte, donc cela devrait fonctionner, non?
Les exemples suivants sont en Python 3, de sorte que les littéraux de chaîne sont plus propres, mais le même problème existe avec des manifestations légèrement différentes sur Python 2 et 3.
Eh bien, c'est faux.
La nouvelle façon recommandée d'utiliser les codecs qui décodent du texte en texte est d'appeler
codecs.decode
directement. Est ce que ça aide?Pas du tout. (De plus, ce qui précède est une erreur UnicodeError sur Python 2.)
Le
unicode_escape
codec, malgré son nom, s'avère supposer que tous les octets non-ASCII sont dans le codage Latin-1 (ISO-8859-1). Vous devriez donc le faire comme ceci:Mais c'est terrible. Cela vous limite aux 256 caractères Latin-1, comme si l'Unicode n'avait jamais été inventé du tout!
Ajout d'une expression régulière pour résoudre le problème
(Étonnamment, nous n'avons pas actuellement deux problèmes.)
Ce que nous devons faire, c'est n'appliquer le
unicode_escape
décodeur qu'aux choses dont nous sommes certains d'être du texte ASCII. En particulier, nous pouvons nous assurer de ne l'appliquer qu'aux séquences d'échappement Python valides, qui sont garanties comme du texte ASCII.Le plan est de trouver des séquences d'échappement à l'aide d'une expression régulière et d'utiliser une fonction comme argument pour
re.sub
les remplacer par leur valeur sans échappement.Et avec cela:
la source
os.sep
du tout? J'essaye de faire ceci:patt = '^' + self.prefix + os.sep ; name = sub(decode_escapes(patt), '', name)
et ça ne marche pas. Le point-virgule est là à la place d'une nouvelle ligne.os.sep
êtes?) Si vous avez des séquences d'échappement contre-obliques dans vos noms de répertoire Windows, la situation est pratiquement irrécupérable.La réponse réellement correcte et pratique pour python 3:
Détails concernant
codecs.escape_decode
:codecs.escape_decode
est un décodeur octets en octetscodecs.escape_decode
décode les séquences d'échappement ascii, telles que:b"\\n"
->b"\n"
,b"\\xce"
->b"\xce"
.codecs.escape_decode
ne se soucie pas ou n'a pas besoin de connaître le codage de l'objet octet, mais le codage des octets échappés doit correspondre au codage du reste de l'objet.Contexte:
unicode_escape
est la solution incorrecte pour python3. Cela est dû au fait queunicode_escape
décode les octets échappés, puis décode les octets en chaîne Unicode, mais ne reçoit aucune information concernant le codec à utiliser pour la deuxième opération.codecs.escape_decode
partir de cette réponse "comment puis-je .decode ('string-escape') en Python3?" . Comme l'indique cette réponse, cette fonction n'est actuellement pas documentée pour python 3.la source
\x
échappements d'octets UTF-8. Mais comme il décode des octets en octets, il ne décode pas - et ne peut pas - décoder les échappements de caractères Unicode non ASCII, tels que les\u
échappements.La
ast.literal_eval
fonction se rapproche, mais elle s'attendra à ce que la chaîne soit correctement citée en premier.Bien sûr, l'interprétation par Python des échappements de barre oblique inverse dépend de la façon dont la chaîne est citée (
""
vsr""
vsu""
, triples guillemets, etc.), vous pouvez donc placer l'entrée utilisateur entre guillemets appropriés et passer àliteral_eval
. Le mettre entre guillemets empêchera égalementliteral_eval
de renvoyer un nombre, un tuple, un dictionnaire, etc.Les choses peuvent encore devenir délicates si l'utilisateur tape des guillemets non entre guillemets du type que vous souhaitez enrouler autour de la chaîne.
la source
myString = "\"\ndoBadStuff()\n\""
,print(ast.literal_eval('"' + myString + '"'))
semble essayer de le code d'exécution. En quoi est-ast.literal_eval
ce différent / plus sûr queeval
?literal_eval
n'exécute jamais de code. D'après la documentation, "Cela peut être utilisé pour évaluer en toute sécurité des chaînes contenant des expressions Python provenant de sources non fiables sans avoir besoin d'analyser les valeurs soi-même."C'est une mauvaise façon de le faire, mais cela a fonctionné pour moi lorsque j'ai essayé d'interpréter des octals échappés passés dans un argument de chaîne.
Il convient de mentionner qu'il existe une différence entre eval et ast.literal_eval (eval étant beaucoup plus dangereux). Voir Utiliser eval () de python contre ast.literal_eval ()?
la source
Le code ci-dessous devrait fonctionner pendant \ n doit être affiché sur la chaîne.
la source
replace
font rien faire), utilise des API extrêmement obsolètes (lesstring
fonctions de module de ce type sont obsolètes à partir de Python 2.0, remplacées par lesstr
méthodes et disparues complètement dans Python 3), et seulement gère le cas spécifique du remplacement d'une seule nouvelle ligne, pas le traitement d'échappement général.