2008-08-17 10 views
11

J'essaye d'implémenter la suppression de chaîne avec Python regex et les références arrières, et cela ne semble pas vouloir fonctionner très bien. Je suis sûr que c'est quelque chose que je fais mal, mais je ne peux pas comprendre ce que ...Expressions régulières Python pour implémenter la suppression de chaîne

>>> import re 
>>> mystring = r"This is \n a test \r" 
>>> p = re.compile("\\\\(\\S)") 
>>> p.sub("\\1", mystring) 
'This is n a test r' 
>>> p.sub("\\\\\\1", mystring) 
'This is \\n a test \\r' 
>>> p.sub("\\\\1", mystring) 
'This is \\1 a test \\1' 

Je voudrais remplacer \\ [char] avec \ [char], mais en Python des backreferences ne semblent pas suivre les mêmes règles que dans toutes les autres implémentations que j'ai jamais utilisées. Quelqu'un pourrait-il jeter quelque lumière?

Répondre

8

est-ce pas ce que Anders 'deuxième exemple fait?

En 2.5 il y a aussi un string-escape d'encodage que vous pouvez appliquer:

>>> mystring = r"This is \n a test \r" 
>>> mystring.decode('string-escape') 
'This is \n a test \r' 
>>> print mystring.decode('string-escape') 
This is 
a test 
>>> 
3

Eh bien, je pense que vous auriez pu manquer le r ou les barres obliques inverses ... mal compté

"\\n" == r"\n" 

>>> import re 
>>> mystring = r"This is \\n a test \\r" 
>>> p = re.compile(r"[\\][\\](.)") 
>>> print p.sub(r"\\\1", mystring) 
This is \n a test \r 
>>> 

qui, si je comprends est ce qui a été demandé.

Je soupçonne que la demande plus commune est la suivante:

>>> d = {'n':'\n', 'r':'\r', 'f':'\f'} 
>>> p = re.compile(r"[\\]([nrfv])") 
>>> print p.sub(lambda mo: d[mo.group(1)], mystring) 
This is \ 
a test \ 
>>> 

L'étudiant intéressé devrait également lire Reflections on Trusting Trust" Ken Thompson, dans laquelle notre héros utilise un exemple similaire pour expliquer les dangers de faire confiance compilateurs vous n'avez pas bootstrap de code machine vous-même.

0

Vous êtes trompé par la représentation de Python de la chaîne de résultat. L'expression Python:

'This is \\n a test \\r' 

représente la chaîne

This is \n a test \r 

qui est je pense que ce que vous vouliez. Essayez d'ajouter 'print' devant chacun de vos appels p.sub() pour imprimer la chaîne actuelle retournée au lieu d'une représentation Python de la chaîne.

>>> mystring = r"This is \n a test \r" 
>>> mystring 
'This is \\n a test \\r' 
>>> print mystring 
This is \n a test \r 
0

L'idée est que je vais lire dans une chaîne échappé, et il échappement d'(une caractéristique manque notamment de Python, que vous ne devriez pas avoir à recourir à des expressions régulières pour en premier lieu). Malheureusement, je ne suis pas dupé par les anti-slash ...

Un autre exemple illustratif:

>>> mystring = r"This is \n ridiculous" 
>>> print mystring 
This is \n ridiculous 
>>> p = re.compile(r"\\(\S)") 
>>> print p.sub('bloody', mystring) 
This is bloody ridiculous 
>>> print p.sub(r'\1', mystring) 
This is n ridiculous 
>>> print p.sub(r'\\1', mystring) 
This is \1 ridiculous 
>>> print p.sub(r'\\\1', mystring) 
This is \n ridiculous 

Ce que je voudrais à imprimer est

This is 
ridiculous 
0

Mark; son deuxième exemple nécessite que tout personnage échappé soit initialement placé dans un tableau, ce qui génère une erreur KeyError si la séquence d'échappement ne se trouve pas dans le tableau. Il mourra sur tout sauf les trois caractères fournis (donnez \ v un essai), et l'énumération de chaque séquence d'échappement possible chaque fois que vous voulez désapparaître une chaîne (ou garder un tableau global) est une très mauvaise solution. Analogue à PHP, cela utilise preg_replace_callback() avec un lambda au lieu de preg_replace(), ce qui est absolument inutile dans cette situation.

Je suis désolé si je suis en train de parler de ça, je suis complètement frustré par Python.Ceci est supporté par tous les autres moteurs d'expressions régulières que j'ai jamais utilisés, et je ne comprends pas pourquoi cela ne fonctionnerait pas.

Merci d'avoir répondu; la fonction string.decode('string-escape') est précisément ce que je cherchais initialement. Si quelqu'un a une solution générale au problème de référence arrière, n'hésitez pas à le poster et je l'accepterai aussi comme réponse.

Questions connexes