You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用re.sub替换指定区间文本并排除含!字符的情况

问题:正则替换排除中间含!的情况

我有一个多行字符串:

Text1 Text2a Text3
Text1 Text2b Text3
Text1 Text2! Text3

需要把Text1和Text3之间的文本替换为Text4,但中间文本包含!的行不处理,期望输出:

Text1 Text4 Text3
Text1 Text4 Text3
Text1 Text2! Text3

我尝试用re.sub处理,但代码不对:

import re
c = re.sub("Text1(.*?)(?!=\!)Text3", "Text1 Text4 Text3", c, flags=re.DOTALL)

结果所有行都被替换了,得到错误输出:

Text1 Text4 Text3
Text1 Text4 Text3
Text1 Text4 Text3

该怎么解决?


解决方法

你原来的正则问题出在断言的位置和逻辑上:(?!=\!)是断言Text3的前一个字符不是!,但第三行里!后面还有空格和Text3,所以这个断言会成立,导致该行被错误替换。

正确的思路是限制Text1和Text3之间的内容完全不包含!,可以用以下两种写法:

写法一:逐字符检查避免!

import re
c = re.sub(r"Text1((?:(?!!).)*?)Text3", r"Text1 Text4 Text3", c, flags=re.DOTALL)
  • 正则解释:
    • (?:(?!!).)*?:非捕获组,每次匹配单个字符前,先检查当前位置后不是!,非贪婪模式确保匹配到最近的Text3就停止。只要中间出现!,这个组就无法匹配到后续的Text3,自然跳过该行替换。

写法二:整体断言无!

import re
c = re.sub(r"Text1(?!.*!)(.*?)Text3", r"Text1 Text4 Text3", c, flags=re.DOTALL)
  • 正则解释:
    • (?!.*!):零宽负向断言,确保从Text1之后到Text3之前的内容里没有!,满足条件才会执行替换。

两种写法都能得到你想要的输出,写法一的效率更高,因为遇到!就会终止匹配,不用扫描到Text3。

内容的提问来源于stack exchange,提问作者Clement Yung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:31:18