5

正規表現を使用して300MBのテキストファイルをスキャンする必要があります。

  • ファイル全体を読み取って変数に取り込むと、700MBを超えるRAMが消費され、「メモリを割り当てることができません」というエラーで失敗します。
  • 一致は2行または3行である可能性があるため、行間のステップインループを使用することはできません。

別の変数に読み込まずに正規表現を使用して完全なファイルスキャンを実行するための怠惰な方法はありますか?

UPD

終わり。これで、この関数を使用してチャンクで読み取ることができます。目標に合わせて変更してください。

def prepare_session_hash(fname, regex_string, start=0)
  @session_login_hash = {}
  File.open(fname, 'rb') { |f|
    fsize = f.size
    bsize = fsize / 8
    if start > 0
      f.seek(start)
    end

    overlap = 200

    while true
      if (f.tell() >= overlap) and (f.tell() < fsize)
        f.seek(f.tell() - overlap)
      end
      buffer = f.read(bsize)
      if buffer
        buffer.scan(s) { |match|
          @session_login_hash[match[0]] = match[1]
        }
      else
        return @session_login_hash
      end
    end
  }
end
4

1 に答える 1

6
  1. ファイルを1行ずつではなく、チャンクでトラバースします。チャンクは、頻繁に出現する文字またはパターン(たとえば、「X」)の出現によって作成されます。
  2. 「X」は、正規表現に存在しないようなものです。つまり、「X」は、正規表現が文字列と一致しない場所です。
  3. 現在のチャンクで正規表現を一致させ、一致を抽出して次のチャンクに進みます。

例:

This is string with multline numbers -2000
2223434
34356666
444564646
. These numbers can occur at 34345
567567 places, and on 67
87878 pages . The problem is to find a good
way to extract these more than 100
0 regexes without memory hogging.

このテキストでは、目的のパターンが数字の文字列であると想定します。たとえば/d+/s、数字の複数行に一致します。次に、ファイル全体を処理してロードする代わりに、チャンク作成パターンを選択できます。この場合はFULL STOPと言い、.このパターンまで読み取りと処理を行ってから、移動します。次のチャンクに。

チャンク#1:

This is string with multline numbers -2000
2223434
34356666
444564646
.

チャンク#2:

These numbers can occur at 34345
567567 places, and on 67
87878 pages

等々。

編集:コメントからも@Rantyの提案を追加します:

または、20行など、数行読んでください。一致するものが見つかったら、一致の最後までクリアして、さらに20行追加します。頻繁に発生する「X」を計算する必要はありません。

于 2012-12-17T08:05:59.967 に答える