web-dev-qa-db-fra.com

Regex Python pour correspondre plusieurs fois

J'essaie de faire correspondre un modèle à des chaînes pouvant contenir plusieurs occurrences du modèle. J'ai besoin de chaque instance séparément. re.findall() devrait le faire mais je ne sais pas ce que je fais mal.

pattern = re.compile('/review: (http://url.com/(\d+)\s?)+/', re.IGNORECASE)
match = pattern.findall('this is the message. review: http://url.com/123 http://url.com/456')

J'ai besoin que ' http://url.com/123 ', http://url.com/456 et les deux nombres 123 et 456 soient différents de la liste match.

J'ai aussi essayé '/review: ((http://url.com/(\d+)\s?)+)/' comme motif, mais pas de chance.

11
mavili

Utilisez ceci. Vous devez placer une "révision" en dehors du groupe de capture pour obtenir le résultat souhaité.

pattern = re.compile(r'(?:review: )?(http://url.com/(\d+))\s?', re.IGNORECASE)

Cela donne une sortie

>>> match = pattern.findall('this is the message. review: http://url.com/123 http://url.com/456')
>>> match
[('http://url.com/123', '123'), ('http://url.com/456', '456')]
14
Narendra Yadala

Vous avez des extra/dans la regex. En python, le motif doit simplement être une chaîne. par exemple. au lieu de cela:

pattern = re.compile('/review: (http://url.com/(\d+)\s?)+/', re.IGNORECASE)

CA devrait etre:

pattern = re.compile('review: (http://url.com/(\d+)\s?)+', re.IGNORECASE)

Généralement, en python, vous utiliseriez une chaîne "raw" comme ceci:

pattern = re.compile(r'review: (http://url.com/(\d+)\s?)+', re.IGNORECASE)

Le r supplémentaire à l'avant de la chaîne vous évite d'avoir à faire beaucoup de backslash s'échappant, etc.

6
John Montgomery

Utilisez une approche en deux étapes: commencez par tout obtenir de "review:" à EOL, puis effectuez une tokenize.

msg = 'this is the message. review: http://url.com/123 http://url.com/456'

review_pattern = re.compile('.*review: (.*)$')
urls = review_pattern.findall(msg)[0]

url_pattern = re.compile("(http://url.com/(\d+))")
url_pattern.findall(urls)
0
til_b