2010-12-13 37 views
7

J'ai été déconner avec la méthode python re modules .search. cur est l'entrée d'un widget d'entrée Tkinter. Chaque fois que j'entre un "\" dans le widget d'entrée, il renvoie cette erreur. Je ne suis pas sûr de savoir quelle est l'erreur ou comment y faire face. Toute opinion serait très appréciée.Python re "erreur d'échappement bidon"

cur est une chaîne

tup [0] est aussi une chaîne

Snippet:

se = re.search(cur, tup[0], flags=re.IGNORECASE) 

L'erreur:

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "C:\Python26\Lib\Tkinter.py", line 1410, in __call__ 
    return self.func(*args) 
    File "C:\Python26\Suite\quidgets7.py", line 2874, in quick_links_results 
    self.quick_links_results_s() 
    File "C:\Python26\Suite\quidgets7.py", line 2893, in quick_links_results_s 
    se = re.search(cur, tup[0], flags=re.IGNORECASE) 
    File "C:\Python26\Lib\re.py", line 142, in search 
    return _compile(pattern, flags).search(string) 
    File "C:\Python26\Lib\re.py", line 245, in _compile 
    raise error, v # invalid expression 
error: bogus escape (end of line) 

Répondre

12

"échappée fictive (fin de ligne)" signifie que votre motif se termine par un antislash. Cela n'a rien à voir avec Tkinter. Vous pouvez dupliquer l'erreur assez facilement dans un shell interactif:

>>> import re 
>>> pattern="foobar\\" 
>>> re.search(pattern, "foobar") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/re.py", line 142, in search 
    return _compile(pattern, flags).search(string) 
    File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/re.py", line 241, in _compile 
    raise error, v # invalid expression 
sre_constants.error: bogus escape (end of line) 

La solution? Assurez-vous que votre motif ne se termine pas avec un seul backslash.

+0

Est-il possible de traiter un \ comme un personnage ordinaire? Similaire à la méthode r "string". – rectangletangle

+2

@ Anteater7171: barre oblique inverse est spécial pour les expressions régulières. Vous avez deux choix: n'utilisez pas d'expressions régulières ou modifiez la chaîne de sorte que la signification spéciale soit supprimée. Pour ce dernier, l'ajout d'un backslash supplémentaire fait l'affaire (ie: le motif '\\' signifie une barre oblique inverse littérale). –

+0

+1 Vous auriez dû ajouter votre dernier commentaire à la réponse. Pour développer le commentaire, dans le contexte de p. re.search cela voudrait dire faire '' pattern = "foobar \\\\" '', c'est-à-dire que vous avez besoin de 4 backslash donc l'argument pattern pour re.search finit par en avoir deux, ce qui ferait une regexp légale. – ThomasH

3

Le premier paramètre à re est le motif à rechercher, donc si 'cur' contient un backslash à la fin de la ligne, ce sera une séquence d'échappement invalide. Vous avez probablement troqué vos arguments autour (je ne sais pas ce que TUP [0] est, mais est-ce votre modèle?) Et il devrait être comme ça

se = re.search(tup[0], cur, flags=re.IGNORECASE) 

Lorsque vous utilisez très rarement entrée utilisateur comme pattern (sauf si vous faites un mécanisme de recherche d'expression régulière, auquel cas vous pourriez vouloir afficher l'erreur à la place).

HTH.

EDIT:
L'erreur qu'il rapporte est que vous utilisez un caractère d'échappement avant la fin de la ligne (qui est ce bogus escape (end of line) moyen), qui est votre modèle se termine par une barre oblique inverse, qui n'est pas motif valide. Le caractère d'échappement (backslash) doit être suivi d'un autre caractère, qui supprime ou ajoute une signification spéciale à ce caractère (je ne sais pas exactement comment python le fait, posix crée des groupes en ajoutant échappement aux parenthèses, perl supprime l'effet de groupe en l'échappant). C'est \* correspond à un astérisque littéral, tandis que * correspond au caractère précédent 0 ou plusieurs fois.

+0

J'utilise l'entrée de l'utilisateur pour rechercher le contenu de tup [0]. Cur est mon modèle. – rectangletangle

+1

@Anteater; eh bien, si cur est le motif, c'est-à-dire que l'utilisateur entre dans le motif, il est évidemment incorrect et l'utilisateur doit en être averti ..? – falstro

+0

selon que l'utilisateur pense entrer une expression régulière. S'ils pensent qu'ils entrent une chaîne fixe, le code doit être corrigé. S'ils pensent qu'ils entrent dans une expression régulière, ils devraient être informés que l'expression est invalide (mais, espérons-le, dans l'esprit d'informer ou d'enseigner plutôt que de châtier). –

3

Si vous essayez de rechercher « roquet » dans « tup [0] » vous devriez le faire à travers « essayer ... sauf ... » bloc pour attraper motif invalide:

try : 
    se = re.search(cur, tup[0], flags=re.IGNORECASE) 
except re.error, e: 
    # print to stdout or any status widget in your gui 
    print "Your search pattern is not valid." 
    # Some details for error: 
    print e 
    # Or some other code for default action. 
12

La solution à ce problème consiste à utiliser une chaîne brute comme texte de remplacement.Ce qui suit ne fonctionnera pas:

re.sub('this', 'This \\', 'this is a text') 

Il lancera l'erreur: évasion bogus (fin de ligne)

Mais ce qui suit fonctionne très bien:

re.sub('this', r'This \\', 'this is a text') 

Maintenant, la question est comment convertir une chaîne générée pendant l'exécution du programme en une chaîne brute en Python. Vous pouvez trouver une solution pour ce here. Mais je préfère utiliser une méthode plus simple de le faire:

def raw_string(s): 
    if isinstance(s, str): 
     s = s.encode('string-escape') 
    elif isinstance(s, unicode): 
     s = s.encode('unicode-escape') 
    return s 

La méthode ci-dessus peut convertir des chaînes seulement ascii et unicode en chaînes brutes. Eh bien, cela a fonctionné très bien pour moi jusqu'à date :)