1

ファイルを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 に一致し、2 番目に多いのは 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

「or」演算子の短絡が役立つことを期待していましたが、スクリプトは大きなファイル (たとえば、サイズが ~1G のファイル) では依然として信じられないほど遅く、修正を開始できる明白で単純なものがあるかどうか疑問に思っていました。それは非常に非効率的です。たとえば、re.compile (ただし、ドキュメントによると、最近の正規表現はキャッシュされており、私はほんの一握りしか持っていません)?

ありがとう

以下のコメントに基づく

最初に join を使用するようにコードを変更し、次に re.compile を使用するように変更しましたが、どちらもこれを高速化していないようです。50,000 行のテスト ファイルで実行され、約 93 秒かかっています。これは、このテスト ファイルで以前に取得していたものでもあります。各正規表現には 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

すべての parseA、parseB 呼び出しを if なしで互いに or'ed にすると、それらのそれぞれが引き続き実行されます。ifを行の先頭に置き、pass必要に応じて実行して、前の関数が成功した場合に次の parseX 関数を実行しないようにするか、ifs のツリーを作成します。

于 2013-09-25T21:43:14.773 に答える