Регулярные выражения 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.