3 votes

Différence de comportement des regex entre Perl et Python ?

J'ai plusieurs adresses e-mail, 'support@company.com' y '1234567@tickets.company.com' .

En perl, je pourrais prendre le To: d'un courriel brut et trouvez l'une ou l'autre des adresses ci-dessus avec

/\w+@(tickets\.)?company\.com/i

En python, j'ai simplement écrit la regex ci-dessus sous forme de '\w+@(tickets\.)?company\.com' en s'attendant au même résultat. Cependant, support@company.com n'est pas trouvé du tout et un findall sur le deuxième retourne une liste contenant seulement 'tickets.' . Il est donc clair que le '(tickets\.)?' est la zone problématique, mais quelle est exactement la différence entre les règles d'expressions régulières de Perl et de Python qui me manque ?

7voto

ephemient Points 87003

La documentation pour re.findall :

findall(pattern, string, flags=0)
    Return a list of all non-overlapping matches in the string.

    If one or more groups are present in the pattern, return a
    list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result.

Desde (tickets\.) est un groupe, findall renvoie cela au lieu de l'ensemble de la correspondance. Si vous voulez l'ensemble de la correspondance, mettez un groupe autour de l'ensemble du motif et/ou utilisez des correspondances non groupées, c'est-à-dire

r'(\w+@(tickets\.)?company\.com)'
r'\w+@(?:tickets\.)?company\.com'

Notez que vous devrez sélectionner le premier élément de chaque tuple retourné par findall dans le premier cas.

4voto

chaos Points 69029

Je pense que le problème réside dans vos attentes en matière de valeurs extraites. Essayez d'utiliser ceci dans votre code Python actuel :

'(\w+@(?:tickets\.)?company\.com)'

2voto

David Berger Points 5459

Deux problèmes me sautent aux yeux :

  1. Vous devez utiliser une chaîne brute pour éviter de devoir échapper " \ "
  2. Vous devez vous échapper " . "

Essayez donc :

r'\w+@(tickets\.)?company\.com'

EDIT

Exemple de sortie :

>>> import re
>>> exp = re.compile(r'\w+@(tickets\.)?company\.com')
>>> bool(exp.match("s@company.com"))
True
>>> bool(exp.match("1234567@tickets.company.com"))
True

1voto

Chas. Owens Points 40887

Il n'y a pas de différence dans les regex, mais il y a une différence dans ce que vous recherchez. Votre regex capture seulement "tickets." s'il existe dans les deux regex. Vous voulez probablement quelque chose comme ceci

#!/usr/bin/python

import re

regex = re.compile("(\w+@(?:tickets\.)?company\.com)");

a = [
    "foo@company.com", 
    "foo@tickets.company.com", 
    "foo@ticketsacompany.com",
    "foo@compant.org"
];

for string in a:
    print regex.findall(string)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X