在使用贪婪字符时,re可以找到最小匹配吗?
免责声明:我不是正则表达式的专家。
我正在使用Python的re模块对很多html文件进行正则匹配。其中一个匹配模式大概是这样的:
<bla><blabla>87765.*</blabla><bla>
我遇到的问题是,它并没有找到所有(比如说)五个匹配的地方,而只找到一个。因为它把所有的匹配结果合并成了一个,使用了第一个匹配中的<bla><blabla>87765
部分和最后一个匹配中的</blabla><bla>
部分。
有没有办法让re找到最小的匹配呢?
4 个回答
1
I believe the regex
<bla><blabla>87765.*?</blabla><bla>
can produce catastrophic backtracking.
Instead, use:
<bla><blabla>87765[^<]*</blabla><bla>
Using atomic grouping (I'm not sure Python supports this),
the above regex becomes
<bla><blabla>(?>(.*?<))/blabla><bla>
在正则表达式中,括号内的内容(像 (?> ... ) 这样的)会被当作一个整体来处理。一旦正则引擎离开这个括号里的内容,它就把这个整体当成一个单独的“标记”。因为这个整体是一个标记,所以一旦找到了匹配的内容,就不能再回头去检查之前的部分了。如果需要回头检查,正则引擎只能回到这个整体之前的标记(在我们的例子中就是那个“^”符号)。如果在这个整体前面没有其他标记,正则就必须从字符串的下一个位置重新开始匹配。值得注意的是,我需要在这个整体里加上“<”符号,以确保它的原子性。差不多就是这样。
5
Python的re模块支持非贪婪匹配。你只需要在通配符模式的末尾加一个?
,比如.*?
。想了解更多,可以查看这个教程。
19
你可以在你的模式中使用一种叫做“懒惰限定符”的东西(想了解更多,可以参考Python文档,里面有关于*?
、+?
和??
的详细说明):
<bla><blabla>87765.*?</blabla><bla>
或者,你可以把<
从可能匹配的字符中排除掉:
<bla><blabla>87765[^<]*</blabla><bla>
只有在<blabla>
和</blabla>
之间没有子标签的情况下。