1

我在 python 中编写了一个简单的脚本,它应该逐行扫描文件并匹配几个不同的正则表达式来重新格式化数据。它的工作原理是这样的:

with open(file) as f:
    for line in f:
        line = line.rstrip('\n')
        parseA(line, anOutPutFile) or parseB(line, anOutPutFile) or parseC(line, anOutPutFile) or parseD(line, anOutPutFile)

每行可以是 A、B、C、D 行之一,也可以没有(大多数匹配 A,第二常见的是 B,等等),下面是一个示例 parseX 函数:

def parseA(line, anOutPutFile):
    regex = '.*-' + bla + ' A ' + '.*\((\d+)\) (\d+) (\w+) (\d+)@(.+) .* (.*)' #(etc..)
    m = re.match(regex, line)
    if m:
        out = 'A' + ',' + m.group(1) + ',' + m.group(2) + ',' + ... #etc
        anOutPutFile.write(out)
        return True
    else:
        return False

我希望“或”运算符的短路会有所帮助,但脚本在大文件(例如,大小约为 1G 的文件)上仍然非常慢,我想知道是否有任何明显和简单的东西我可以开始修改在其中,这是非常低效的。例如 re.compile (但文档说最近的正则表达式被缓存,我只有少数)?

谢谢

基于以下评论

我首先将代码更改为使用 join ,然后使用 re.compile ,但似乎都没有加快速度。它在一个 50,000 行的测试文件上运行,大约需要 93 秒或 1 秒。这也是它之前在这个测试文件上所采取的。我在每个正则表达式中有 8 到 12 个组,其中有 5 个。这就是我将代码更改为:

regexA = re.compile('.*0' + bla + ' A ' + '.*\((\d+)\) (\d+) (\w+) (\d+)@(.+) .* (.*) .* .* foo=far fox=(.*) test .*')
regexB = re.compile(#similar)
regexC = re.compile('.*0' + bla + ' C ' + '.*\((\d+)\) (\d+) (\w+) (\d+)@(.+) foo=(\d+) foo2=(\d+) foo3=(\d+)@(.+) (\w+) .* (.*) .* .* foo4=val foo5=(.*) val2 .*')
regexD = re.compile(#similar)
regexE = re.compile(#similar)

#include two of the regex above fully to get an idea of what they look like
#now this is an example of one of the parse funcs for regexA

def parseA(line,anOutputFile):
    m = regexA.match(line)
    if m:
        out = ''.join(['A',',',m.group(1),',',m.group(2),',',#etc])
        anOutputFile.write(out)
        return True
    else:
        return False

也许加入列表不是你的意思?并且一旦顶层编译 5 个正则表达式并没有帮助。

4

2 回答 2

0

您是否考虑过将文件写出函数并简化,因为它们似乎都是一样的。

将行和编译的正则表达式作为参数的解析函数。

def parse(line, regex, label):
    m = regex.match(line)
    if m:
        return ','.join([label] + m.groups())

然后文件写入可以发生在主循环中

with open(file) as f:
    for line in f:
        line = line.rstrip('\n')
        outline = parse(line, regexA, 'A') or parse(line, regexB, 'B') or parse(line, regexC, 'C') or parse(line, regexD, 'D')
        if outline:
            anOutPutFile.write(outline)
于 2013-09-25T22:09:24.983 回答
-1

在没有 if 的情况下让所有 parseA、parseB 调用或相互调用仍然会执行它们中的每一个。如果前一个成功,则在行的开头放置一个if,然后在pass必要时执行以防止执行下一个 parseX 函数,或者创建一个 ifs 树。

于 2013-09-25T21:43:14.773 回答