在 python 上使用 re.findall 函数时无法获得正确的结果

Can't get the right result when using re.findall function on python

我想用正则表达式匹配正确的字符串,但是我不能。

import re
str = "<meta apple <meta" \
  "we go<meta" \
  "goto mac <meta td yiyang ziyou" \
  "net<meta aaask zoie where to go?" \
  "<meta " \
  "buy mac"
r = re.findall("<meta(?!.*<meta).*mac", str, re.S)

我认为会匹配到两个字符串,一个是<meta goto mac,另一个是<meta buy mac,但我只得到了最后一个。为什么?我用的是PyCharm5.0.3,python的版本是3.5.1。谢谢。

问题是你有一个否定的 look-ahead 运算符 (?!.*<meta) 这意味着对于任何匹配,必须 而不是 <meta稍后在字符串中。

因此,只有你的最后一个 <meta 字符串被匹配,因为只有它能满足这个条件。

另一个答案说了为什么你只得到最后一个匹配的原因,并注意你的输入字符串中没有换行符,你不需要添加 re.S 修饰符。 <meta(?!.*<meta) 否定前瞻断言 <meta 旁边不存在字符串 <meta,所以这只发生在最后一个。

In-order 要得到结果,你的正则表达式必须是

<meta(?:(?!<meta).)*?mac

示例:

>>> s = "<meta apple <meta" \
  "we go<meta" \
  "goto mac <meta td yiyang ziyou" \
  "net<meta aaask zoie where to go?" \
  "<meta " \
  "buy mac"
>>> s
'<meta apple <metawe go<metagoto mac <meta td yiyang ziyounet<meta aaask zoie where to go?<meta buy mac'
>>> re.findall(r'<meta(?:(?!<meta).)*?mac', s)
['<metagoto mac', '<meta buy mac']

正则表达式中的 .* 耦合是一个有用、强大的工具,但它也非常危险。有时您可能想让正则表达式更具体一些。至于具体原因,其他帖子已经回答了。但是如果你真的想寻找一个解决方案来匹配你在这里寻找的项目是它的正则表达式:

import re

string = "<meta apple <meta" \
"we go<meta" \
"goto mac <meta td yiyang ziyou" \
"net<meta aaask zoie where to go?" \
"<meta " \
"buy mac"

print re.findall('(<meta[\w\s]*mac)',string,re.DOTALL)