22

I'm trying to match a pattern against strings that could have multiple instances of the pattern. I need every instance separately. re.findall() should do it but I don't know what I'm doing wrong.

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')

I need 'http://url.com/123', http://url.com/456 and the two numbers 123 & 456 to be different elements of the match list.

I have also tried '/review: ((http://url.com/(\d+)\s?)+)/' as the pattern, but no luck.

2
  • just remove the review: portion as the second http won't have that before it. Commented Jul 1, 2013 at 15:07
  • yes but I need that there, it's part of the regex. I don't need ANY url there, just the ones following the string 'review:' Commented Jul 1, 2013 at 15:08

3 Answers 3

26

Use this. You need to place 'review' outside the capturing group to achieve the desired result.

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

This gives output

>>> 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')]
Sign up to request clarification or add additional context in comments.

4 Comments

that does the job, thanks! the ? after (?:review ) is also critical as it didn't give me all matches without it. ;)
Don't forget to import re
What about doing it without findall? I.e. for cases when you need to match many cases, but this would be just a part of a match?
regex101.com is a neat tool for testing this out.
6

You've got extra /'s in the regex. In python the pattern should just be a string. e.g. instead of this:

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

It should be:

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

Also typically in python you'd actually use a "raw" string like this:

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

The extra r on the front of the string saves you from having to do lots of backslash escaping etc.

Comments

2

Use a two-step approach: First get everything from "review:" to EOL, then tokenize that.

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.