6

reファイル全体を文字列(またはメモリ)にロードせずに、(モジュールを使用して)正規表現で大きなファイルを解析する方法は? メモリ マップされたファイルは、コンテンツをある種の遅延文字列に変換できないため、役に立ちません。モジュールはreコンテンツ引数として文字列のみをサポートします。

#include <boost/format.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/regex.hpp>
#include <iostream>

int main(int argc, char* argv[])
{
    boost::iostreams::mapped_file fl("BigFile.log");
    //boost::regex expr("\\w+>Time Elapsed .*?$", boost::regex::perl);
    boost::regex expr("something usefull");
    boost::match_flag_type flags = boost::match_default;
    boost::iostreams::mapped_file::iterator start, end;
    start = fl.begin();
    end = fl.end();
    boost::match_results<boost::iostreams::mapped_file::iterator> what;
    while(boost::regex_search(start, end, what, expr))
    {
        std::cout<<what[0].str()<<std::endl;
        start = what[0].second;
    }
    return 0;
}

私の要件を実証するため。Python で使用したいのと同じように、C++ (およびブースト) を使用して短いサンプルを作成しました。

4

3 に答える 3

7

すべてが正常に動作するようになりました (Python 3.2.3 と Python 2.7 のインターフェイスにはいくつかの違いがあります)。(Python 3.2.3 で) 有効なソリューションを得るには、検索パターンの前に b" を付ける必要があります。

import re
import mmap
import pprint

def ParseFile(fileName):
    f = open(fileName, "r")
    print("File opened succesfully")
    m = mmap.mmap(f.fileno(), 0, access = mmap.ACCESS_READ)
    print("File mapped succesfully")
    items = re.finditer(b"\\w+>Time Elapsed .*?\n", m)
    for item in items:
        pprint.pprint(item.group(0))

if __name__ == "__main__":
    ParseFile("testre")
于 2012-07-27T16:44:15.893 に答える
6

それは、実行している解析の種類によって異なります。

実行している解析が行単位の場合、次のようにファイルの行を反復処理できます。

with open("/some/path") as f:
    for line in f:
        parse(line)

それ以外の場合は、一度にチャンクを読み取って解析することにより、チャンクのようなものを使用する必要があります。明らかに、これには、一致させようとしているものがチャンク境界と重複する場合に備えて、より注意を払う必要があります。

于 2012-07-26T17:06:45.620 に答える
1

Julian のソリューションを詳しく説明するには、次のように、連続する行を保存して連結することにより、(複数行の正規表現を実行する場合) チャンクを実現できます。

list_prev_lines = []
for i in range(N):
    list_prev_lines.append(f.readline())
for line in f:
    list_prev_lines.pop(0)
    list_prev_lines.append(line)
    parse(string.join(list_prev_lines))

これにより、現在の行が含まれる前の N 行の実行中のリストが保持され、複数行のグループが単一の文字列として解析されます。

于 2012-07-26T17:15:48.257 に答える