0

我想创建一个 python 脚本来比较一个工具生成的两个日志文件(名为foo.log和)。bar.log日志文件有一些可以忽略的行和一些不能忽略的行(用于比较)。

我创建了正则表达式来标识可以忽略的行。以下是我实现代码的方式:

import re

p_1 = re.compile(...) # Pattern 1 to be ignored
p_2 = re.compile(...) # Pattern 2 to be ignored
p_3 = re.compile(...) # Pattern 3 to be ignored
...
p_n = re.compile(...) # Pattern n to be ignored

with open("foo.log", mode = 'r') as foo:
    with open("foo_temp.log", mode = 'w') as foo_temp:
        for foo_lines in foo:
            if p_1.match(foo_lines):
                continue
            elif p_2.match(foo_lines):
                continue
            elif p_3.match(foo_lines):
                continue
            ...
            ...
            ...
            elif p_n.match(foo_lines):
                continue
            else:
                foo_temp.write(foo_lines)

with open("bar.log", mode = 'r') as bar:
    with open("bar_temp.log", mode = 'w') as bar_temp:
        for bar_lines in bar:
            if p_1.match(bar_lines):
                continue
            elif p_2.match(bar_lines):
                continue
            elif p_3.match(bar_lines):
                continue
            ...
            ...
            ...
            elif p_n.match(bar_lines):
                continue
            else:
                bar_temp.write(bar_lines)

运行脚本后,我会得到两个文件foo_temp.logbar_temp.log稍后我会使用 WinMerge 手动比较它们。以下是我的问题:

1)有什么方法可以优化我使用正则表达式的方式(我实际上是正则表达式的新手,我觉得在这方面有很多可以优化的地方)

2)稍后当我必须添加要忽略的新模式时,我可以从用户的角度更容易地添加新模式吗?(目前我需要添加一个新模式,然后在 2 个位置检查 - 一个 forfoo.log和一个 for bar.log

3)我听说在处理巨大的文件时使用了生成器。虽然我比较的日志相对较小(最大 50MB),但我是否应该研究如何使用生成器并将它们合并到我的脚本中?

4) 除了使用 WinMerge 创建foo_temp.logbar_temp.log执行手动检查之外,有没有一种方法可以让我在 Python 本身中进行(减少的文件的)比较?filecmp也许来自模块的东西?

注意:一些可以忽略的行在两个日志中都出现混乱(无序):例如,foo.log以下可能是模式:

Line 1: <<Pattern_1: Ignore>>
Line 2: <<Pattern_2: Do not Ignore>>
Line 3: <<Pattern_3: Do not Ignore>>
Line 4: <<Pattern_4: Do not Ignore>>
Line 5: <<Pattern_5: Ignore>>

bar.log可能具有以下模式:

Line 1: <<Pattern_1: Ignore>>
Line 2: <<Pattern_5: Ignore>>
Line 3: <<Pattern_2: Do not Ignore>>
Line 4: <<Pattern_3: Do not Ignore>>
Line 5: <<Pattern_4: Do not Ignore>>

请注意,一旦我们删除了可以忽略的行,这两个文件将具有相同的模式。出于这个原因,我决定一次性删除所有可以忽略的行,然后对缩小的文件进行比较。

4

1 回答 1

1

我不知道您想到的是哪种比较-difflib可能会派上用场-但据我所知,您的代码减少到

import re

raw_patterns = [r'aaa', r'bbb', r'ccc']
patterns = [re.compile(p) for p in raw_patterns]

names = "foo", "bar"

for name in names:
    with open(name + ".log", "r") as in_fp, open(name + "_temp.log", "w") as temp:
        for line in in_fp:
            if not any(patt.match(line) for patt in patterns):
                temp.write(line)

该原则被称为 DRY,意思是“不要重复自己”。每当您发现自己重复代码时,您可以考虑将重复抽象掉。在这种情况下,我们可以将模式和文件名放在列表中,然后遍历它们。

--

在生成器方面,这是真的:您不需要构造中间文件。您可以创建一个仅产生您关心的行的对象,然后对其进行迭代。例如:

from itertools import zip_longest

def informative_lines(filename):
    with open(filename) as infile:
        for line in infile:
            if not any(patt.match(line) for patt in patterns):
                yield line

paired_lines = zip_longest(informative_lines("foo.log"),
                           informative_lines("bar.log"))

for i, (line0, line1) in enumerate(paired_lines):
    if line0 != line1:
        print('mismatch at non-ignored line #', i)
        print(line0)
        print(line1)
        raise Exception("problem!")

print("hooray, files matched!")
于 2013-01-28T06:07:02.550 回答