以下代码根据其子字符串出现(我在这里说的是关键字)以及与之关联的文本从文件中提取行:
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
方法实现这一目标吗?
由于内容未在我的文件中修复,因此无法使用某些正则表达式来提取它。逻辑是,找到关键字并获取前面的所有内容,除非出现下一个关键字。
答案 0 :(得分:1)
以下是我建议的解决方法:
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 demo的输出:
['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})
- non-capturing group,其中包含|
alternation operator列出的备选方案(例如Total item value|Total weight|Total volume
).*
- LF以外的任何0 +字符(其余部分)(?:[\r\n]+(?!(?:{0})).*)*
- 重复0次或以上:
[\r\n]+(?!(?:{0}))
- 一个或多个LF或/和CR符号([\r\n]+
)未跟随任何keywords
项目.*
- 其余部分