20

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.

mavili
  • 3,385
  • 4
  • 30
  • 46
  • just remove the review: portion as the second http won't have that before it. – abc123 Jul 01 '13 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:' – mavili Jul 01 '13 at 15:08

3 Answers3

24

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')]
Narendra Yadala
  • 9,554
  • 1
  • 28
  • 43
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.

John Montgomery
  • 8,868
  • 4
  • 33
  • 43
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)
til_b
  • 327
  • 5
  • 15