Match lines between two patterns in Python with regular expressions
我正在解析日志文件,其中包含有关许多作业的事件的行,这些行由作业ID标识。我正在尝试在Python中的两种模式之间获取日志文件中的所有行。
我已经阅读了这篇非常有用的文章。如何在两种模式之间选择线?并已经使用
1 | awk '/pattern1/,/pattern2/' file |
由于我正在用Python脚本处理日志信息,因此我正在使用
我知道
1 2 3 4 5 6 7 8 9 10 11 | import bz2 import re logfile = '/some/log/file.bz2' PATTERN = r"/{0}/,/{1}/".format('pattern1', 'pattern2') # example: PATTERN = r"/0001.server;Considering job to run/,/0040;pbs_sched;Job;0001.server/" re.compile(PATTERN) with bz2.BZ2File(logfile) as fh: match = re.findall(PATTERN, fh.read()) |
但是,
在
的行
1 2 3 4 5 | literal 47 literal 50 literal 48 literal 49 literal 57 |
和两个说出
1 | any None |
我可以使用像这样的循环来解决问题,例如在两个模式之间进行python打印,包括包含模式的行,但我会尽可能避免嵌套的for-if循环。我相信
我正在使用Python 2.7.9。
将整个日志文件读取到内存中通常是一个坏主意,因此我将为您提供逐行解决方案。我假设您的示例中的点是模式中唯一变化的部分。我还要假设您要在列表列表中收集行组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import bz2 import re with_delimiting_lines = True logfile = '/some/log/file.bz2' group_start_regex = re.compile(r'/0001.server;Considering job to run/') group_stop_regex = re.compile(r'/0040;pbs_sched;Job;0001.server/') group_list = [] with bz2.BZ2File(logfile) if logfile.endswith('.bz2') else open(logfile) as fh: inside_group = False for line_with_nl in fh: line = line_with_nl.rstrip() if inside_group: if group_stop_regex.match(line): inside_group = False if with_delimiting_lines: group.append(line) group_list.append(group) else: group.append(line) elif group_start_regex.match(line): inside_group = True group = [] if with_delimiting_lines: group.append(line) |
请注意,
使用纯正则表达式,您可以将
1 | re.findall("pattern1.*?pattern2", input, re.DOTALL) |
它与
1 2 3 | re.findall("[^\ ]*pattern1.*?pattern2[^\ ]*", input, re.DOTALL) |
在这里尝试!
请注意,我回答您的问题是出于教学的考虑,但是应首选Walter Tross的解决方案。