如何实现支持N层级的正则表达式递归字符串拆分通用函数?
需求:实现N层级正则递归拆分文本
我希望创建一个或一组函数,利用正则表达式(RegEx)按递归层级将大文本/字符串拆分为多个子串,输出格式为包含各层级匹配名称/模式与最底层文本的元组列表。
示例输出
[("Chapter 1", "Section 1", "Subsection 1", "Text belonging to this particular subsection"), ("Chapter 1", "Section 2", "Subsection 1", "Other text belonging to this particular subsection"), ("Chapter 1", "Section 2", "Subsection 2", "Another text belonging to this particular subsection"), ("Chapter 2", "Section 1", "Subsection 1", "Yet another text belonging to this particular subsection")]
当前已实现的硬编码3层级逻辑
我已经实现了固定3层级(章节、小节、子小节)的拆分逻辑,对应层级有正则分隔符,代码如下:
import re def my_split(text: str, delim: str): # split string splitted = re.split(delim, text) # divide into patterns split on and texts following patterns names = splitted[1::2] texts = splitted[2::2] return names, texts # split into chapters chapter_names, chapter_texts = my_split(full_text, delim_chapter) chapters = list(zip(chapter_names, chapter_texts)) # create list to save level names and lowest level split text subsections_list = [] # iterate through chapters and find if there are sections present for chapter_name, chapter_text in chapters: # check if sections exist and create sections list if re.search(delim_section, chapter_text): section_names, section_texts = my_split(chapter_text, delim_section) sections = list(zip(section_names, section_texts)) else: # create artificial section name section_names, section_texts = ['Unique section'], [chapter_text] sections = list(zip(section_names, section_texts)) for section_name, section_text in sections: # divide into subsections subsection_names, subsection_texts = my_split(section_text, delim_subsection) subsections = list(zip(subsection_names, subsection_texts)) # get repeated chapter and section names to put in tuples with subsections and text chapter_names = [chapter_name] * len(subsections) section_names = [section_name] * len(subsections) # create list of tuples containing all subsections names and text chapter_section_subsection_text = list( zip(chapter_names, section_names, subsection_names, subsection_texts)) # save to list subsections_list.append(chapter_section_subsection_text) subsections_flat_list = [item for sublist in subsections_list for item in sublist]
问题
我需要一个支持输入任意N个正则分隔符的通用函数,以实现N层级的拆分。目前卡在如何构思各递归层级的拆分逻辑上,恳请提供建议。此外,是否也可以通过复杂正则表达式实现该需求?我最初选择递归方案是因为逻辑自然,但也接受其他思路。
解决方案
一、递归实现通用N层级拆分
核心思路是用递归函数,每一层处理当前分隔符,把当前层级的名称和剩余文本传递给下一层,直到所有分隔符处理完毕,再生成包含所有层级名称和最终文本的元组。
通用递归函数代码
import re def my_split(text: str, delim: str): splitted = re.split(delim, text) # 处理没有匹配到分隔符的情况:返回空名称列表和原文本 if len(splitted) == 1: return [], [text.strip()] names = [name.strip() for name in splitted[1::2]] texts = [text.strip() for text in splitted[2::2]] # 处理拆分后名称和文本数量不匹配的情况(比如文本结尾是分隔符) if len(names) > len(texts): names = names[:len(texts)] return names, texts def recursive_split(text: str, delims: list, current_path: tuple = ()): # 递归终止条件:没有更多分隔符,返回当前路径+文本的元组 if not delims: return [(current_path + (text.strip(),))] current_delim = delims[0] names, texts = my_split(text, current_delim) results = [] # 如果没有匹配到当前分隔符,生成一个默认名称的路径 if not names: default_name = f"Level {len(current_path)+1} (Unique)" results.extend(recursive_split(text, delims[1:], current_path + (default_name,))) else: # 遍历当前层级的每个名称和对应文本,递归处理下一层 for name, txt in zip(names, texts): results.extend(recursive_split(txt, delims[1:], current_path + (name,))) return results # 使用示例 # 定义各层级的正则分隔符(比如章节是"Chapter \d+",小节是"Section \d+"等) delim_chapter = r"(Chapter \d+)" delim_section = r"(Section \d+)" delim_subsection = r"(Subsection \d+)" full_text = """ Chapter 1 Text before section Section 1 Subsection 1 Text belonging to this particular subsection Subsection 2 Another text Section 2 Subsection 1 Other text belonging to this particular subsection Chapter 2 Section 1 Subsection 1 Yet another text belonging to this particular subsection """ # 调用函数,传入分隔符列表(顺序从最高层级到最低层级) final_result = recursive_split(full_text, [delim_chapter, delim_section, delim_subsection]) for item in final_result: print(item)
代码说明
my_split函数做了增强:处理没有匹配到分隔符的情况,以及拆分后名称和文本数量不一致的问题,返回清理后的名称和文本。recursive_split是核心递归函数:- 每次取第一个分隔符处理当前文本;
- 如果当前分隔符没有匹配到,生成默认名称,继续处理下一层;
- 如果匹配到,遍历每个名称和文本,把当前名称加入路径,递归处理剩余分隔符;
- 当所有分隔符处理完,把最终文本加入路径,形成完整元组。
二、非递归迭代实现
如果不想用递归,也可以用迭代的方式,逐层处理每个分隔符,维护当前层级的路径和文本集合:
import re def my_split(text: str, delim: str): splitted = re.split(delim, text) if len(splitted) == 1: return [], [text.strip()] names = [name.strip() for name in splitted[1::2]] texts = [text.strip() for text in splitted[2::2]] if len(names) > len(texts): names = names[:len(texts)] return names, texts def iterative_split(text: str, delims: list): # 初始状态:路径为空,文本是输入文本 current_level = [((), text.strip())] for delim in delims: next_level = [] for path, txt in current_level: names, texts = my_split(txt, delim) if not names: # 没有匹配到分隔符,生成默认名称 default_name = f"Level {len(path)+1} (Unique)" next_level.append((path + (default_name,), txt)) else: for name, sub_txt in zip(names, texts): next_level.append((path + (name,), sub_txt)) current_level = next_level # 把路径和最终文本合并成元组 return [path + (txt,) for path, txt in current_level] # 使用示例和递归版一致 final_result = iterative_split(full_text, [delim_chapter, delim_section, delim_subsection])
三、单一复杂正则表达式的可能性?
理论上可以用捕获组+正向预查来匹配所有层级,但存在几个问题:
- 正则表达式会非常复杂,尤其是当N很大时,难以维护和调试;
- 无法处理层级缺失的情况(比如某个章节没有小节),必须严格匹配所有层级的结构;
- 提取结果后仍需要额外处理来生成要求的元组格式,并不比递归/迭代更简洁。
因此不推荐用单一正则实现,递归或迭代的方式逻辑更清晰、扩展性更强。
内容的提问来源于stack exchange,提问作者Ouroboroski
相关产品推荐
相关产品推荐

