首页 > 解决方案 > 根据子字符串索引查找内容

问题描述

以下代码根据其子字符串的出现(我将在这里说关键字)以及与之关联的文本从文件中提取行:

from itertools import count

def find_content_blocks_by_keywords(lines, keywords):
    keyword_indexes = sorted([i for i, line in zip(count(), lines) for 
    keyword in keywords if re.search(keyword, line)])  
    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_keywords(lines, keywords):

样本结果:

[[],
 ['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.findall或任何其他re方法来实现这一点吗?

由于内容在我的文件中不固定,因此无法使用某些正则表达式来提取它。逻辑是,找到关键字并获取它前面的所有内容,除非出现下一个关键字。

标签: pythonregex

解决方案


这是我建议的修复方法:

from itertools import count
import re

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.']

pat = r'(?m)^(?:{0}).*(?:[\r\n]+(?!(?:{0})).*)*'.format("|".join([re.escape(x) for x in keywords]))
print(re.findall(pat, "\n".join(lines)))

Python 演示的输出:

['Total item value RSX 05,018.88\n', 'Total weight 90,969 EUR\n', 'Total volume -97.93 X3 Sca.\n\n197.939 X3 Sca.']

图案说明

  • (?m)-re.MULTILINE修饰符^匹配行的开始
  • ^- 一行的开始
  • (?:{0})- 一个非捕获组,将包含使用|交替运算符列出的备选方案(例如Total item value|Total weight|Total volume
  • .*- 除 LF 以外的任何 0+ 个字符(该行的其余部分)
  • (?:[\r\n]+(?!(?:{0})).*)*- 0次或多次重复:
    • [\r\n]+(?!(?:{0}))- 1 个或多个 LF 或/和 CR 符号 ( [\r\n]+) 未跟任何keywords项目
    • .*- 线路的其余部分

推荐阅读