web-dev-qa-db-fra.com

Comment trouver des correspondances qui se chevauchent avec une expression rationnelle?

>>> match = re.findall(r'\w\w', 'hello')
>>> print match
['he', 'll']

Puisque\w\w signifie deux caractères, "he" et "ll" sont attendus. Mais pourquoi "el" et "lo" pas correspondent à la regex?

>>> match1 = re.findall(r'el', 'hello')
>>> print match1
['el']
>>>
48
futurenext110

findall ne produit pas de correspondances qui se chevauchent par défaut. Cette expression fait cependant:

>>> re.findall(r'(?=(\w\w))', 'hello')
['he', 'el', 'll', 'lo']

Ici (?=...) est une assertion lookahead :

(?=...) correspond si ... correspond à la suivante, mais ne consomme aucun des fichiers chaîne. Ceci est appelé une affirmation d'anticipation. Par exemple, Isaac (?=Asimov) ne correspond à 'Isaac ' que s’il est suivi de 'Asimov'.

79
Otto Allmendinger

Vous pouvez utiliser le nouveau module d'expression rationnelle Python , qui prend en charge les correspondances qui se chevauchent.

>>> import regex as re
>>> match = re.findall(r'\w\w', 'hello', overlapped=True)
>>> print match
['he', 'el', 'll', 'lo']
28
David C

À l'exception de l'assertion de longueur nulle, le caractère de l'entrée sera toujours utilisé dans la correspondance. Si jamais vous souhaitez capturer plusieurs caractères dans la chaîne d'entrée plus d'une fois, vous aurez besoin d'une assertion de longueur nulle dans l'expression régulière.

Il existe plusieurs assertions de longueur nulle (par exemple ^ (début de la ligne/entrée), $ (fin de la ligne/entrée), \b (limite de mot)), mais des contournements ((?<=) recherche positive derrière et (?=) recherche positive ) sont le seul moyen de capturer le texte qui se chevauchent à partir de l’entrée. Les contours négatifs ((?<!) négatif, (?!) négatif) ne sont pas très utiles ici: s'ils affirment true, la capture à l'intérieur a échoué; s'ils affirment false, la correspondance échoue. Ces assertions sont nuls (comme mentionné précédemment), ce qui signifie qu'elles s'affirmeront sans consommer les caractères de la chaîne d'entrée. Ils correspondront en fait à une chaîne vide si l'assertion réussit.

En appliquant les connaissances ci-dessus, une expression rationnelle qui convient à votre cas serait:

(?=(\w\w))
8
nhahtdh

Je ne suis pas un expert en regex, mais je voudrais répondre à la même question question .

Si vous souhaitez utiliser un groupe de capture avec le lookahead:

exemple de regex: (\ d) (? =.\1)

chaîne: 5252

cela correspondra aux 5 premiers ainsi qu'aux 2 premiers

Le (\ d) consiste à créer un groupe de capture, (? =\D\1) consiste à faire correspondre tout chiffre suivi du groupe de capture 1 sans utiliser la chaîne, afin de permettre le chevauchement.

0
Obay Abd-Algader