正则表达式报错look-behind requires fixed-width pattern 替换需求求助
解决Python正则look-behind可变宽度错误并实现目标替换
这个报错是因为Python标准re模块对后行断言(look-behind)的要求很严格:它只支持固定长度的模式,而你写的(?<!\(|(?<=eq ))里,两个备选分支的长度不一致——\(是1个字符,eq 是3个字符(e、q加空格),所以触发了look-behind requires fixed-width pattern错误。
需求分析
先明确我们要替换的是哪些单引号:
- 不能是紧跟在
(后面的(比如('hel'lo')里的第一个'要保留) - 不能是紧跟在
eq后面的(比如eq 'some ...里的第一个'要保留) - 不能是在
)前面或者字符串末尾的(比如('hel'lo')里的最后一个'要保留) - 其他所有单引号都要替换成双引号
''
解决方案(标准re模块)
我们可以把“既不是(后面,也不是eq 后面”的条件拆成两个独立的固定宽度后行断言(逻辑与的关系),这样就符合re模块的要求了。
代码示例:
import re text = "('hel'lo') eq 'some 'variable he're'" # 两个固定宽度的后行断言:前面既不是(,也不是eq pattern = re.compile(r"(?<!\()(?<!eq )'(?!\)|\Z)") result = pattern.sub("''", text) print(result)
运行后输出正好是你想要的:
('hel''lo') eq 'some ''variable he''re'
补充:用第三方regex模块简化写法
如果你可以安装第三方的regex模块(它支持可变宽度的后行断言),可以直接用更直观的备选分支写法:
import regex text = "('hel'lo') eq 'some 'variable he're'" pattern = regex.compile(r"(?<!\(|eq )'(?!\)|\Z)") result = pattern.sub("''", text) print(result)
这个写法和你最初的思路更接近,不需要拆分后行断言,regex模块会自动处理不同长度的备选分支。
为什么原来的写法不行?
Python标准re模块的后行断言不允许备选分支有不同的长度,比如(?<!a|bb)这种写法就会报错,因为a是1字符,bb是2字符。而拆分后的(?<!a)(?<!bb)是两个独立的固定宽度后行断言,逻辑上等价于“既不是a后面,也不是bb后面”,就可以正常工作了。
内容的提问来源于stack exchange,提问作者User1493
相关产品推荐
相关产品推荐

