如何用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
相关产品推荐
相关产品推荐

