Python re.sub 使用非贪婪模式 (.*?) 和字符串结尾 ($) 变成贪婪模式!

6 投票
2 回答
5808 浏览
提问于 2025-04-16 07:35

代码:

str = '<br><br />A<br />B'
print(re.sub(r'<br.*?>\w$', '', str))

本来应该返回 <br><br />A,但是却返回了一个空字符串 ''

有什么建议吗?

2 个回答

1

这里说的“非贪婪”匹配不会像你想的那样在后面开始。它会先找到第一个 <br,然后再非贪婪地匹配后面的内容,但实际上这些内容需要匹配到字符串的末尾,因为你指定了 $

如果你想让它按你想的那样工作,可以使用

/<br[^<]*?>\w$/

不过,通常不建议用正则表达式来解析HTML,因为某些属性的值里面可能会有 <>

7

贪婪匹配是从左到右进行的,反过来就不行。简单来说,就是“除非匹配失败,否则就不匹配”。下面是具体的过程:

  1. 正则表达式引擎在字符串的开头匹配到 <br
  2. .*? 现在被忽略,因为它是懒惰的匹配。
  3. 尝试匹配 >,成功了。
  4. 接着尝试匹配 \w,但失败了。这个时候就有意思了——引擎开始回溯,看到 .*? 这个规则。在这种情况下,. 可以匹配第一个 >,所以还有希望能匹配上。
  5. 这种情况一直持续,直到正则表达式到达斜杠。然后 >\w 可以匹配,但 $ 失败了。再次,引擎回到懒惰的 .* 规则,继续匹配,直到匹配到 <br><br />A<br />B

幸运的是,有个简单的解决办法:通过替换 <br[^>]*>\w$,你就不允许在标签外进行匹配,这样就能替换最后一个出现的匹配。
严格来说,这对HTML来说效果不好,因为标签属性中可能包含 > 字符,但我想这只是个例子。

撰写回答