Python正则如何处理带换行符的多行文本|解决匹配空白、提取失败问题
一、前言日常开发中使用Pythonre正则时几乎所有人都会踩同一个坑单行字符串匹配一切正常一旦文本包含换行符正则直接匹配不到内容re.findall返回空列表。典型场景提取Markdown中json /python 包裹的多行代码块截取多行注释、分段日志、多行接口返回文本抓取HTML/富文本中跨多行的标签内容像前文需求一样提取大段跨换行JSON字符串。出现该问题的根源不是正则表达式写错而是Python正则内置的匹配规则限制。本文完整讲解换行处理原理、两套通用解决方案、实战案例与避坑技巧。二、核心底层规则点号.默认不匹配换行正则中最常用的万能匹配符.存在硬性限制默认规则.匹配除换行符\n之外的所有字符。举个直观例子importre text第一行 第二行 第三行# 尝试用.匹配全部内容会失败resre.findall(r.,text)print(res)# 输出[第一行, 第二行, 第三行].只会匹配单行内容遇到换行直接终止无法一次性抓取跨多行的整块文本。如果我们想匹配json 和 中间跨多行的内容直接写json(.?)必然返回空列表这就是你之前代码失效的根本原因。三、两种主流跨行匹配解决方案方案1添加标志位 re.Sre.DOTALL【推荐】re.S全称DOTALL作用让.可以匹配换行符\n开启后点号真正代表「任意所有字符」跨行匹配一键生效。语法re.findall(正则,文本,flagsre.S)实战修复你之前提取JSON代码块的案例importre str1 随便一段前置文字 json[{content:第一篇 战略管理,level:0},{content:1 目的,level:2}]后置备注文字‘’’增加 flagsre.S 支持跨行匹配res re.findall(r’json(.?), str1, flagsre.S)if res:json_content res[0].strip() # 清除首尾多余换行空格print(“提取到多行JSON\n”, json_content)执行后可以完整取出中间所有换行的JSON文本完美解决提取空白问题。 补充别名re.DOTALL 和 re.S 完全等价二者随便使用。 ### 方案2不使用标志位替换万能匹配符 [\s\S] 如果项目规范不允许添加flag、或者部分环境无法传参可以用 [\s\S] 替代 .。 - \s所有空白字符空格、制表符、换行 \n - \S所有非空白字符 二者组合 [\s\S] 全部字符天然支持换行不需要额外标志位。 改造上例正则 python # [\s\S]? 替代 .? res re.findall(rjson([\s\S]?), str1)效果和re.S完全一致适合不方便修改flag参数的场景。四、补充容易混淆的 re.M 多行模式和换行匹配无关很多新手会混淆re.M和re.S这里明确区分re.S控制.是否匹配换行用于跨多行抓取整块内容re.MMULTILINE仅修改^和$的匹配规则^匹配每行开头$匹配每行结尾不改变点号.的行为无法解决跨行提取失败问题。错误示范很多人踩坑# 只加re.M不加re.S依旧匹配不到跨多行内容resre.findall(rjson(.?),str1,re.M)print(res)# [] 空列表如果需要同时开启两种模式使用|分隔re.findall(pattern,text,re.S|re.M)五、常用实战案例案例1提取多行Python代码块importre md_text 测试文本 pythondeftest():print(多行函数)return123“”pattern r’python([\s\S]?)’code re.findall(pattern, md_text)[0].strip()print(code)### 案例2匹配跨多行HTML标签内容 python html div classbox 第一行文字 第二行文字 /div res re.findall(rdiv classbox(.?)/div, html, re.S) print(res[0].strip())案例3逐行匹配不需要跨行仅遍历每行如果需求不是抓取整块多行内容而是单独匹配每一行无需开启re.S直接循环结果即可log2026-01-01 日志1 2026-01-02 日志2 2026-01-03 日志3# 匹配所有数字开头日志行linesre.findall(r^\d{4}-\d{2}-\d{2}.*,log,re.M)print(lines)六、开发避坑优化技巧正则字符串统一使用原始字符串 r正则表达式前缀加r避免\n、\s等转义符被Python提前解析防止匹配异常。错误写法json(.?)标准写法rjson(.?)提取后使用strip()清理多余换行空格跨行匹配出来的内容首尾通常自带换行、空白调用.strip()去除冗余空白字符。非贪婪匹配?避免匹配范围过大使用(.?)/([\s\S]?)非贪婪模式防止文本中存在多个 时一次性匹配到最后一个结束标记。判断匹配结果非空再取值匹配失败返回空列表直接取res[0]会报索引错误增加判断resre.findall(rjson(.?),str1,re.S)ifres:contentres[0].strip()else:print(未找到对应代码块)七、总结Python正则.默认不能匹配换行符这是多行文本提取空白的核心原因主流解决方案添加flagsre.S让.支持换行或使用[\s\S]替代.re.M仅作用于行首尾符^/$不能解决跨行抓取问题不要混用混淆处理Markdown代码块、多行标签、分段日志等场景优先使用re.S方案代码简洁易维护规范使用原始字符串、非贪婪匹配、空值判断减少线上正则报错。掌握以上规则后所有带换行符的文本正则匹配问题都可以一次性解决。