Python 正则表达式 - re.search() 与 re.findall() 的区别
我在学校要写一个Python的正则表达式脚本,用来提取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()
正确地按照这个表达式来提取呢?或者我是不是哪里搞错了?
2 个回答
6
你在这个正则表达式中只捕捉到了最后的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
这里解释了子模式。子模式1是通过findall捕捉到的内容。
19
findall
这个函数会返回一个匹配结果的列表,文档中提到:
如果模式中有一个或多个分组,返回的将是一个分组的列表;如果模式有多个分组,返回的将是一个元组的列表。
所以,你之前的表达式有一个分组,在字符串中匹配了3次,最后一次匹配的结果是0.
要解决你的问题,可以使用:exp = "(?:\d{1,3}\.){3}\d{1,3}"
;通过使用非分组的版本,就不会返回分组,所以在这两种情况下都能得到匹配结果。