2013-09-25 35 views
1

我在python中编写了一个简单的脚本,它应该逐行扫描文件并匹配一对不同的正则表达式来重新格式化数据。它的工作原理是这样的:缓慢的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(但文档说,最近的正则表达式被缓存,我只有少数)?

感谢

基于评论BELOW

我改变了代码首先使用连接,然后使用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个正则表达式顶级没有帮助。

+0

你第一次尝试编译你的正则表达式parseX发生吗?见7.2.2节开头(http://docs.python.org/2/library/re.html) – prgao

+0

我不是因为它说最近使用过的那些被缓存,我只有少数,但我试图无论如何,以确保。 –

+0

对于例如'mmap'文件,然后're.finditer'所有A匹配,然后所有B匹配,等等,而不是调用're.match' 100M次,可能会快很多。如果你需要以正确的顺序交错线条,但是仍然可行,那将会有点棘手。 – abarnert

回答

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) 
+0

哦,这太漂亮了,我猜这是有效的,因为None评估结果为False –

+0

@Palace肯定,但它有速度优势吗? –

-1

让所有的parseA,parseB调用or'ed对方没有一个if仍然会执行其中的每一个。将if放在行的开头,如果需要,只需执行pass,以防止在先前成功执行下一个parseX函数或创建ifs树。

+0

我认为'或'运营商短路,并会停止第一次真正的回报? –

+0

这个答案是错误的,或**做**短路。 http://stackoverflow.com/questions/2580136/does-python-support-short-circuiting –

+0

@PalaceChan和Graem Stuart,杜,从来没有,我没有看到parseX函数中的返回语句...你是那么绝对正确。 –