J'ai la chaîne suivante:

a = '''"The cat is running to the door, he does not look hungry anymore".

Said my mom, whispering.'''

Notez les sauts de ligne . En python, la chaîne sera: 'The cat is running to the door, he does not look hungry anymore".\n \n Said my mom, whispering.'

J'ai cette expression régulière: pattern = u'^("|«)(.*?)("|»)(.*?)\u000A{1,}(.*?)'

Et j'ai utilisé comme suit en Python:

>>> import re
>>> a = '''"The cat is running to the door, he does not look hungry anymore".

Said my mom, whispering.'''
>>> pattern = u'^("|«)(.*?)("|»)(.*?)\u000A{1,}(.*?)'
>>> re.search(pattern, a).groups()
>>> ('"', 'The cat is running to the door, he does not look hungry anymore', '"', '.', '')

Pourquoi la dernière partie (Said my mom, whispering.) n'est pas interceptée par l'expression régulière? J'attends quelque chose comme ça:

>>> ('"', 'The cat is running to the door, he does not look hungry anymore', '"', '.', 'Said my mom, whispering.')

Pouvez-vous s'il vous plaît me clarifier ce que je fais mal?

1
gglasses 12 juil. 2015 à 21:02

3 réponses

Meilleure réponse

Il suffit de supprimer le ?. Et il est également préférable d'inclure le modificateur DOTALL car le point dans votre regex par défaut ne correspondra pas aux nouveaux caractères de ligne.

pattern = u'(?s)^("|«)(.*?)("|»)(.*?)\u000A{1,}(.*)'

Notez que .*? est réticent ou non gourmand, ce qui signifie qu'il faut faire correspondre n'importe quel caractère zéro ou plusieurs fois sans gourmandise. Ainsi, il cesse de correspondre une fois qu'il trouve une chaîne vide.

1
Avinash Raj 12 juil. 2015 à 18:10

Votre saisie ne commence pas par le devis et l'expression régulière l'exige. Ensuite, il y a un modèle de saut de ligne manquant pour la deuxième ligne. Et troisièmement, la correspondance paresseuse .*? ne correspondra à rien, car elle peut correspondre à une chaîne vide, donc si vous n'utilisez pas une ancre $ ou une correspondance gourmande.

De plus, il n'est pas efficace d'utiliser des lettres simples en alternance, donc je préfère utiliser une classe de caractères pour de tels cas: ("|«) => ["«].

Avec la classe de raccourcis \s, vous pouvez faire correspondre non seulement les sauts de ligne mais aussi les espaces, ce qui "coupe" les résultats dans les groupes de capture.

Voici ma suggestion:

import re
p = re.compile(r'^(["«])?(.*?)(["»])?\.\s*(.*?)\s*(.*)')
test_str = "The cat is running to the door, he does not look hungry anymore\".\n\nSaid my mom, whispering."
print re.search(p, test_str).groups()

Voir la démo

0
Wiktor Stribiżew 12 juil. 2015 à 18:26

Le problème avec votre expression est que le groupe (.*?) est réticent , ce qui signifie qu'il doit correspondre au moins de texte possible. Dans la mesure où vous ne demandez pas que la correspondance "s'ancre" à la fin de l'entrée, le deuxième groupe est vide.

L'ajout de $ à la fin de l'expression régulière résoudra ce problème:

pattern = u'^("|«)(.*?)("|»)(.*?)\u000A{1,}(.*?)$'
0
dasblinkenlight 12 juil. 2015 à 18:09