91 votes

Comment trouver des correspondances qui se chevauchent avec une regexp ?

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

Depuis \w\w signifie que deux caractères, "he" et "ll" sont attendus. Mais pourquoi est-ce que "el" et "lo no correspond à la regex ?

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

133voto

Otto Allmendinger Points 11853

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

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

Ici (?=...) es un assertion de lookahead :

(?=...) correspond si ... matches suivants, mais ne chaîne. Cela s'appelle une assertion lookahead. [ ] Isaac (?=Asimov) correspondra à 'Isaac ' seulement s'il est suivi par 'Asimov' .

46voto

David C Points 916

Vous pouvez utiliser le nouveau module Python regex 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']

11voto

nhahtdh Points 28167

Sauf dans le cas d'une assertion de longueur nulle, les caractères de l'entrée seront toujours consommés dans la correspondance. Si vous êtes dans le cas où vous voulez capturer un certain caractère dans la chaîne d'entrée plus d'une fois, vous aurez besoin de l'assertion de longueur zéro dans la regex.

Il existe plusieurs assertions de longueur nulle (par ex. ^ (début de l'entrée/ligne), $ (fin de l'entrée/ligne), \b (limite du mot)), mais des solutions de contournement ( (?<=) un regard positif et (?=) look-ahead positif) sont le seul moyen de capturer du texte se chevauchant à partir de l'entrée. Les look-arounds négatifs ( (?<!) un regard négatif en arrière, (?!) negative look-ahead) ne sont pas très utiles ici : si elles affirment vrai, alors la capture à l'intérieur a échoué ; si elles affirment faux, alors la correspondance échoue. Ces assertions sont de longueur zéro (comme mentionné précédemment), ce qui signifie qu'elles affirmeront sans consommer les caractères de la chaîne d'entrée. Elles correspondent à une chaîne vide si l'assertion est acceptée.

En appliquant les connaissances ci-dessus, une regex qui fonctionne pour votre cas serait :

(?=(\w\w))

0voto

Je ne suis pas un expert en regex mais j'aimerais répondre à ma question similaire. question .

Si vous voulez 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

En (\d) est de faire un groupe de capture, (?=\d\1) est de correspondre à tout chiffre suivi du groupe de capture 1 sans consommer la chaîne, ce qui permet le chevauchement.

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