Pourquoi xx donne-t-il quelque chose de différent de x {2} ? Veuillez consulter l'exemple suivant:

import re

lines = re.findall(r'".*?"".*?"', '"x""y"')
print(lines) # yields: ['"x""y"']

lines = re.findall(r'(".*?"){2}', '"x""y"')
print(lines) # yields: ['"y"']
1
user9611000 18 avril 2018 à 00:23

4 réponses

Meilleure réponse

Selon la documentation de findall, si vous avez un groupe dans l'expression régulière, il retourne la liste de ces groupes, soit en tant que tuple pour 2+ groupes ou en tant que chaîne pour 1 groupes. Dans votre cas, vos deux expressions rationnelles ne sont pas simplement xx contre x{2}, mais plutôt la seconde est (x){2}, qui a un groupe, lorsque la première expression régulière n'a pas de groupe.

Par conséquent, "x" correspond au groupe la première fois, puis "y" correspond au groupe la deuxième fois. Cela remplit votre regex globale, mais "y" remplace "x" par la valeur du groupe 1.

La façon la plus simple de résoudre ce problème dans votre exemple est de convertir votre groupe en un groupe non correspondant: (?:".*?"){2}. Si vous voulez deux groupes, un pour "x" et un pour "y", vous devez répéter le groupe deux fois: (".*?")(".*?"). Vous pouvez potentiellement utiliser des groupes nommés pour simplifier cette répétition.

0
scnerd 17 avril 2018 à 21:44

AFAIK, findall() est capture group first, s'il y a un groupe de capture dans l'expression régulière appliquée, alors findall() renvoie uniquement les valeurs du groupe de capture.

Et seulement lorsqu'il n'y a pas de groupe de capture dans l'expression régulière appliquée, findall() renvoie fullmatch values.

Par conséquent, si vous voulez que findall() renvoie fullmatch value, vous ne devez pas utiliser le groupe de capture dans l'expression régulière comme ceci

(?:".*?"){2}

Dans lequel (?: ... ) indiquent non-capture group.

Ainsi, en python

print(re.findall(r'(?:".*?"){2}', '"x""y"'))
0
Thm Lee 18 avril 2018 à 05:14

La première expression est "X puis Y, où Y correspond accidentellement à la même chose que X" .

La deuxième expression est "(X) {répéter deux fois}" . Le groupe 1 ne peut pas contenir XX, car le groupe 1 ne correspond pas à XX. Il correspond à X.

En d'autres termes: le contenu du groupe ne change pas uniquement à cause d'un quantificateur extérieur au groupe.

Une façon de remédier à la deuxième expression est de créer un groupe externe (et de rendre le groupe interne non capturant)

lines = re.findall(r'((?:".*?"){2})', '"x""y"')
0
Tomalak 17 avril 2018 à 21:59

À propos de votre deuxième motif (".*?"){2}:

Une citation des règles de correspondance

Si un groupe est contenu dans une partie du modèle correspondant plusieurs fois, la dernière correspondance est renvoyée.

Et findall procède comme suit:

Si un ou plusieurs groupes sont présents dans le modèle, renvoyez une liste de groupes;

Votre modèle (".*?"){2} signifie que (".*?") doit correspondre deux fois de suite, et selon la première règle, seul le contenu de la dernière correspondance est capturé.

Pour vos données, findall ne trouve la séquence (".*?"){2} qu'une seule fois, il renvoie donc une liste constituée du dernier groupe capturé pour une seule correspondance: ['"y"'].

Cet exemple le rendrait plus évident:

import re
print (re.findall(r'(\d){2}', 'a12b34c56'))
# ['2', '4', '6']

Vous pouvez voir que findall trouve la séquence (\d){2} trois fois et pour chacun retourne le dernier contenu capturé pour le groupe (\d).

Maintenant à propos de votre premier modèle: ".*?"".*?".
Celui-ci ne contient pas de sous-groupes et, selon findall encore une fois, dans ce cas, il renvoie:

toutes les correspondances non chevauchantes du modèle dans la chaîne, sous forme de liste de chaînes.

Donc pour vos données c'est ['"x""y"'].

0
wolfrevokcats 17 avril 2018 à 22:18