4 votes

lookahead et expressions régulières non capturantes

J'essaie de faire correspondre la partie locale d'une adresse e-mail avant le caractère @ avec :

LOCAL_RE_NOTQUOTED = """
((
\w         # alphanumeric and _
| [!#$%&'*+-/=?^_`{|}~]          # special chars, but no dot at beginning
)
(
\w         # alphanumeric and _
| [!#$%&'*+-/=?^_`{|}~]          # special characters
| ([.](?![.])) # negative lookahead to avoid pairs of dots. 
)*)
(?<!\.)(?:@)           # no end with dot before @
"""

Testé avec :

re.match(LOCAL_RE_NOTQUOTED, "a.a..a@", re.VERBOSE).group()

donne :

'a.a..a@'

Pourquoi le @ imprimé dans la sortie, même si j'utilise un groupe non capturant. (?:@) ?

Testé avec :

 re.match(LOCAL_RE_NOTQUOTED, "a.a..a@", re.VERBOSE).groups()

donne :

('a.a..a', 'a', 'a', None)

Pourquoi la regex ne rejette-t-elle pas la chaîne avec une paire de points ? '..' ?

8voto

Tim Pietzcker Points 146308

Vous confondez les groupes de non-capture (?:...) et les assertions lookahead (?=...) .

Les premiers participent au match (et font donc partie de l'équipe de l'UE). match.group() qui contient la correspondance globale), ils ne génèrent simplement pas de rétro-référence ( $1 etc. pour une utilisation ultérieure).

Le deuxième problème (Pourquoi le double point est-il apparié ?) est un peu plus délicat. Il est dû à une erreur dans votre regex. Vous voyez, lorsque vous avez écrit (en raccourcissant pour faire le point)

[+-/]

vous avez écrit "Faire correspondre un caractère entre + y / et en ASCII, le point est juste entre les deux (ASCII 43-47 : +,-./ ). Par conséquent, la première classe de caractères correspond au point, et l'assertion lookahead n'est jamais atteinte. Vous devez placer le tiret à la fin de la classe de caractères pour le traiter comme un tiret littéral :

((
\w         # alphanumeric and _
| [!#$%&'*+/=?^_`{|}~-]          # special chars, but no dot at beginning
)
(
\w         # alphanumeric and _
| [!#$%&'*+/=?^_`{|}~-]          # special characters
| ([.](?![.])) # negative lookahead to avoid pairs of dots. 
)*)
(?<!\.)(?=@)           # no end with dot before @

Et bien sûr, si vous voulez utiliser cette logique, vous pouvez la rationaliser un peu :

^(?!\.)                   # no dot at the beginning
(?:
[\w!#$%&'*+/=?^_`{|}~-]   # alnums or special characters except dot
| (\.(?![.@]))            # or dot unless it's before a dot or @ 
)*
(?=@)                     # end before @

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