Регулярные выражения Python - re.search() vs re.findall()

В школе я должен написать Python RE script, который извлекает IP-адреса. Регулярное выражение, которое я использую, похоже, работает с re.search(), но не с re.findall().

exp = "(\d{1,3}\.){3}\d{1,3}"
ip = "blah blah 192.168.0.185 blah blah"
match = re.search(exp, ip)
print match.group()

Совпадение для этого всегда 192.168.0.185, но его отличие, когда я делаю re.findall()

exp = "(\d{1,3}\.){3}\d{1,3}"
ip = "blah blah 192.168.0.185 blah blah"
matches = re.findall(exp, ip)
print matches[0]

0.

Мне интересно, почему re.findall() дает 0. когда re.search() дает 192.168.0.185, так как я использую одно и то же выражение для обеих функций.

И что я могу сделать, чтобы сделать так, чтобы re.findall() действительно правильно выполнял это выражение? Или я делаю какую-то ошибку?

Ответ 1

findall возвращает список совпадений и из документации:

Если в шаблоне присутствует одна или несколько групп, верните список групп; это будет список кортежей, если шаблон имеет более одной группы.

Итак, ваше предыдущее выражение имело одну группу, которая соответствовала 3 раз в строке, где последнее совпадение было 0.

Чтобы исправить вашу проблему, используйте: exp = "(?:\d{1,3}\.){3}\d{1,3}"; с помощью негрупповой версии нет возвращенных групп, поэтому совпадение возвращается в обоих случаях.

Ответ 2

Вы только фиксируете 0 в этом регулярном выражении, так как это будет последний, который поймал.

Измените выражение, чтобы захватить весь IP-адрес, а повторяющаяся часть - не захватывающая группа:

In [2]: ip = "blah blah 192.168.0.185 blah blah"

In [3]: exp = "((?:\d{1,3}\.){3}\d{1,3})"

In [4]: m = re.findall(exp, ip)

In [5]: m
Out[5]: ['192.168.0.185']

In [6]: 

И если это помогает объяснить регулярное выражение:

In [6]: re.compile(exp, re.DEBUG)
subpattern 1
  max_repeat 3 3
    subpattern None
      max_repeat 1 3
        in
          category category_digit
      literal 46
  max_repeat 1 3
    in
      category category_digit

Это объясняет подшаблоны. Subpattern 1 - это то, что захватывает findall.