Python re.sub正则替换连续空格如何保留字符串开头原有空格
问题根因
你之前写的负向断言写法存在逻辑漏洞:(?<!^)仅能排除「前一个位置是字符串开头」的匹配点,开头的连续空格序列中,除了第一个字符位置,其余所有位置都不满足「前面是字符串起始位」的判断条件,正则会从开头空格串的后续位置开始匹配3-20位连续空格,最终把开头的长空格截断替换为3个,和预期不符。
另外注意Python 2.7自带的re模块不支持可变长度的后行断言,想靠单条复杂正则直接排除所有前置空格的匹配场景很容易触发兼容问题。
推荐解决方案(Python2.7全兼容)
最稳妥无bug的实现方式是拆分前置空格单独处理,不需要纠结正则边界的复杂判断,逻辑可解释性强,不会出现误替换:
- 先提取字符串开头的所有连续前置空格,这部分内容原封不动保留
- 对字符串剩下的非前置部分,执行「3-20位连续空格替换为3个空格」的规则
- 把保留的前置空格和处理后的内容拼接得到最终结果
对应实现代码:
import re a = " command1 command2 abc def command3 ghi" # 提取开头所有前置空格 leading_space = re.match(r'^(\s*)', a).group(1) # 截掉前置空格后处理剩余内容 content_without_leading = a[len(leading_space):] processed_content = re.sub(r'\s{3,20}', ' ', content_without_leading) # 拼接得到结果 final_result = leading_space + processed_content
执行后final_result的值完全匹配预期:开头的10个前置空格完整保留,字符串中间所有长度3-20的连续空格都被统一替换为3个空格。
单正则写法(可选)
如果不想做字符串拆分,可以通过匹配「前面紧邻非空格字符」的连续空格规则实现,该写法依赖固定长度后行断言,Python2.7可支持,但无法匹配替换字符串末尾的长空格,适配性不如拆分法:
result = re.sub(r'(?<=\S)\s{3,20}', ' ', a)
内容的提问来源于stack exchange,提问作者user19416874
相关产品推荐
相关产品推荐

