查找重叠匹配项
给定一个字符串(来自文本文件的一行),我想找到所有像这样构建的子字符串:
[[ words ]]
例如:
[[foo [[ bar ]]
应该返回这两个:
[[foo [[ bar ]]
和
[[ bar ]]
另一个例子:
[[foo]] 和 [[bar]]
应该产生:
[[foo]]
和
[[bar]]
我想到了一个公式:
\[\[.+\]\]
但它工作得不太好(匹配得太多了)。
谢谢大家的帮助!
2 个回答
1
这个内容使用了正向前瞻的方式来捕捉并返回你重叠的匹配结果:
>>> re.findall(r'(?=(\[\[.*?\]\]))', '[[foo [[ bar ]]')
# ['[[foo [[ bar ]]', '[[ bar ]]']
>>> re.findall(r'(?=(\[\[.*?\]\]))', '[[foo]] and [[bar]]')
# ['[[foo]]', '[[bar]]']
注意在*
这个量词后面有一个?
,这让你的匹配变得不贪婪,也就是说它会尽量匹配最少的内容。
2
重叠匹配:使用前瞻
如果你想要懒惰的重叠匹配,可以使用这个正则表达式:
(?=(\[\[.?*\]\]))
在Python中:
import re
pattern = r"(?=(\[\[.*?\]\]))"
print(re.findall(pattern, "[[foo [[ bar ]]"))
print(re.findall(pattern, "[[foo]] and [[bar]]"))
输出结果:
['[[foo [[ bar ]]', '[[ bar ]]']
['[[foo]]', '[[bar]]']
如果你想要“贪婪的重叠”,可以使用 (?=(\[\[.*\]\]))
输出结果:
['[[foo [[ bar ]]', '[[ bar ]]']
['[[foo]] and [[bar]]', '[[bar]]']
解释
- 前瞻
(?= ... )
表示括号内的内容可以被匹配(但实际上并不匹配它,这样我们就能找到重叠的匹配) - 括号中的 `([[.*]])` 将匹配到的字符串捕获到第1组
\[\[
匹配[[
.*
贪婪地匹配任何字符- 在
.*?
中,星号量词被?
变得“懒惰”,这样点号只会匹配所需的最少字符,以便下一个符号能够匹配(最短匹配)。如果没有?
,.*
会先匹配整个字符串,然后回溯到只需要的地方,以便下一个符号能够匹配(最长匹配)。 \]\]
匹配]]
参考资料