Python正则表达式 - re.search()vs re.findall()

use*_*906 20 python regex

对于学校我应该写一个提取IP地址的Python RE脚本.我正在使用的正则表达式似乎可以使用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()
Run Code Online (Sandbox Code Playgroud)

对此的匹配总是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.
Run Code Online (Sandbox Code Playgroud)

我想知道为什么re.findall()收益率为0.当re.search()收益率为192.168.0.185时,因为我对两个函数使用相同的表达式.

我能做些什么来实现它re.findall()才能真正遵循正确的表达方式?还是我犯了某种错误?

Kru*_*Kru 14

findall 返回匹配列表,并从文档中:

如果模式中存在一个或多个组,则返回组列表; 如果模式有多个组,这将是一个元组列表.

因此,您之前的表达式有一个组在最后一个匹配的字符串中匹配3次 0.

要解决您的问题,请使用: exp = "(?:\d{1,3}\.){3}\d{1,3}"; 通过使用非分组版本,没有返回的组,因此在两种情况下都返回匹配.


Tyr*_*ave 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]: 
Run Code Online (Sandbox Code Playgroud)

如果它有助于解释正则表达式:

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
Run Code Online (Sandbox Code Playgroud)

这解释了子模式。子模式 1 是 findall 捕获的内容。