能否用re.findall或其他re方法直接实现关键词内容块提取?
用re模块实现按关键词提取关联内容块
当然可以借助re模块来实现这个需求!你的核心逻辑是:定位所有包含关键词的行,然后将文本分割为「上一个关键词结束到当前关键词前」「当前关键词到下一个关键词前」的块,我们可以通过re的定位功能结合切片,或者用re.split配合分组来实现。
方法一:用re.finditer定位关键词行,再切片
这种思路和你原代码的逻辑很像,只是用re.finditer来精准找到所有匹配关键词的行索引:
import re def find_content_blocks_by_re(lines, keywords): # 编译关键词正则,用re.escape处理特殊字符,避免正则语法干扰 keyword_pattern = re.compile('|'.join(map(re.escape, keywords))) # 遍历所有行,收集包含关键词的行索引 keyword_indexes = [] for idx, line in enumerate(lines): if keyword_pattern.search(line): keyword_indexes.append(idx) # 按索引分割成块,逻辑和原代码完全对齐 return [lines[i:j] for i, j in zip([0]+keyword_indexes, keyword_indexes+[None])]
测试原示例:
keywords = ['Total item value', 'Total weight', 'Total volume'] lines = ['Total item value RSX 05,018.88\n', 'Total weight 90,969 EUR\n', 'Total volume -97.93 X3 Sca.\n', '197.939 X3 Sca.'] result = find_content_blocks_by_re(lines, keywords) print(result)
输出和原代码完全一致:
[[], ['Total item value RSX 05,018.88\n'], ['Total weight 90,969 EUR\n'], ['Total volume -97.93 X3 Sca.\n', '197.939 X3 Sca.']]
方法二:拼接文本后用re.split分割
如果可以把行列表拼接成完整字符串,也可以用re.split结合捕获分组直接提取块:
import re def find_content_blocks_by_re_split(lines, keywords): text = ''.join(lines) # 构建多行模式正则:匹配任意关键词开头的行,同时捕获该行作为分隔符 keyword_pattern = re.compile(r'(?m)^.*(?:' + '|'.join(map(re.escape, keywords)) + ').*$') # split时保留分隔符,得到「分隔符前内容」「分隔符」「分隔符前内容」的交替列表 parts = re.split(r'(' + keyword_pattern.pattern + r')', text) blocks = [] # 处理开头到第一个关键词前的内容块 if parts[0].strip() == '': blocks.append([]) else: blocks.append(parts[0].splitlines(keepends=True)) # 组合分隔符行和后续内容行,形成每个关键词对应的块 for i in range(1, len(parts), 2): block_lines = parts[i].splitlines(keepends=True) + parts[i+1].splitlines(keepends=True) blocks.append(block_lines) return blocks
测试后输出结果同样和原代码一致。
为什么不直接用re.findall?
直接用re.findall很难直接生成这种分块结构,因为findall更适合提取符合固定模式的独立片段,而我们的需求是分割文本并保留分割点前后的关联内容,所以结合索引定位或者split+分组的方式,会更贴合需求场景。
另外,两种方法都用到了re.escape来处理关键词,这能避免关键词中的特殊正则字符(比如.、*)干扰匹配,在关键词不确定的场景下非常关键。
内容的提问来源于stack exchange,提问作者Laxmikant
相关产品推荐
相关产品推荐

