Python中按指定一级章节标题拆分文本并保留标题在各段开头的实现方案
Python中按指定一级章节标题拆分文本并保留标题在各段开头的实现方案
嗨,我来帮你搞定这个文本拆分的问题!你的需求很明确:只在**一级章节标题(## 加1-9的单个数字,比如## 1、## 2)**处拆分,把标题留在对应段落的开头,同时完全忽略像## 1.1这种带小数点的子章节。下面我给你两种靠谱的Python实现思路,都是实际项目里常用的方法,你可以按需选。
方法一:用re.split结合正向预查,简单直接
原理:我们用正则的正向预查标记拆分位置,这样split的时候不会吃掉章节标题,反而会把标题留在拆分后的下一个段落开头。正则会精准匹配一级标题,自动跳过带小数点的子章节。
import re # 你的原始文本 raw_text = "Start of text. ## 1 Introduction This is the introduction. ## 1.1 Introduction continues. ## 2 Next part This part keeps going." # 正则解析: # (?=## [1-9](?!\.)) 是正向预查,意思是: # 匹配一个"位置",这个位置后面紧跟 "## " + 1-9的单个数字,且数字后面不是小数点(排除子章节) split_result = re.split(r'(?=## [1-9](?!\.))', raw_text) # 处理开头的前置文本:如果开头有非章节内容(比如示例里的"Start of text."),和第一个章节块合并 if len(split_result) >= 2 and split_result[0].strip(): split_result[0] = split_result[0] + split_result.pop(1) # 输出结果验证 for idx, part in enumerate(split_result, 1): print(f"=== 第 {idx} 个拆分块 ===") print(part.strip()) # strip()清理多余空格,按需保留或删除
运行后你会得到完全符合需求的结果:
- 第一个块是开头前置文本 + ##1的内容 + ##1.1的子章节内容
- 第二个块是##2的完整内容
而且完全不会在##1.1的位置拆分,完美匹配你的要求!
方法二:用re.findall直接匹配目标块,更省心
原理:直接用正则写出我们想要的每个块的规则,一次性匹配出所有结果,不需要后续合并处理,适合追求逻辑清晰的场景。
import re raw_text = "Start of text. ## 1 Introduction This is the introduction. ## 1.1 Introduction continues. ## 2 Next part This part keeps going." # 正则解析: # 分两种情况匹配: # 1. (?:^.*?(?=## [1-9](?!\.)))?## [1-9](?!\.).*?(?=## [1-9](?!\.)) # 匹配「开头到第一个一级标题的内容 + 该一级标题到下一个一级标题前的所有内容」 # 2. ## [1-9](?!\.).* # 匹配「最后一个一级标题到文本结尾的所有内容」 # re.DOTALL 让.能匹配换行符,即使你的文本有换行也不影响 blocks = re.findall( r'(?:^.*?(?=## [1-9](?!\.)))?## [1-9](?!\.).*?(?=## [1-9](?!\.))|## [1-9](?!\.).*', raw_text, re.DOTALL ) # 输出结果 for idx, block in enumerate(blocks, 1): print(f"=== 第 {idx} 个拆分块 ===") print(block.strip())
这个方法会直接返回你需要的所有块,不需要额外处理开头文本,正则已经帮你把前置内容和第一个章节合并好了。如果你的文本有多个一级章节(比如##1、##2、##3),它也能自动拆分出对应的3个块,每个块都包含自己的一级标题和所有子章节内容。
一些实用的细节调整建议
- 如果需要匹配更大范围的一级标题数字(比如0-99),把正则里的
[1-9]改成\d+,同时保留(?!\.)排除子章节即可 - 如果章节标题格式有细微变化(比如##后面有多个空格、数字后面是换行),把
##改成##\s+(匹配任意数量的空白字符) - 示例里的
strip()是为了清理多余空格,如果你需要保留原始的空格和换行,直接去掉这个方法就行
两种方法都能完美解决你的问题,你可以根据自己的代码风格选择,第一种更灵活,第二种更直接。如果还有其他格式细节要调整,随时改正则就行,正则的弹性很大~




