巨大なファイルから多数のパターンをGrepします。

巨大なファイルから多数のパターンをGrepします。

毎日約200,000行ずつ増えるファイルがあり、すべて次のように3行からなる塊で構成されています。

1358726575123       # key
    Joseph Muller   # name
    carpenter       # job
9973834728345
    Andres Smith
    student
7836472098652
    Mariah Anthony
    dentist

現在、約10,000の主要パターンを抽出した別のファイルがあります1358726575123。その後、forこれらのパターンでループを実行し、最初のファイルと比較する必要があります。ファイルにこれらのパターンが含まれていない場合は、さらに処理するために3番目のファイルにパターンを保存します。

for number in $(grep -o '[0-9]\{12\}' file2); do  # finds about 10.000 keys
     if ! grep -q ^$number$ file1; then           # file1 is a huge file
         printf "$number\n" >>file3               # we'll process file3 later
     fi
done

サンプルコードは大きなファイルを10,000回grepします。私はこのループを約10,000回実行します。1分に1回、一日中

大容量ファイルが増え続けていますが、これらすべてをすばやく作成し、いくつかのCPUを節約するにはどうすればよいですか?キーごとにファイルを並べ替えるか(それではどうすれば?)、プレーンテキストの代わりにデータベースを使用するのが役に立つかどうか疑問に思います。

答え1

もちろん、問題は大きなファイルに対してgrepを10,000回実行することです。両方のファイルを一度だけ読み取る必要があります。スクリプト言語を使用したくない場合は、次のようにします。

  1. ファイル1からすべての数値を抽出してソートします。
  2. ファイル2からすべての数値を抽出してソートします。
  3. comm2番目のリストの内容だけを取得するには、ソートされたリストを実行してください。

このような:

$ grep -o '^[0-9]\{12\}$' file1 | sort -u -o file1.sorted
$ grep -o  '[0-9]\{12\}'  file2 | sort -u -o file2.sorted
$ comm -13 file1.sorted file2.sorted > file3

望むよりman comm

ログファイルなどの大容量ファイルを毎日切り捨てることができる場合は、ソートされた数のキャッシュを保持でき、毎回解析する必要はありません。

答え2

awkこの回答は公開された回答に基づいています。痛み..同じ状況では、この方法(私のシステムでは)
よりも倍速です。comm600万行メインファイルと10000キー...(FNR、NRを使用するように更新されました)

現在のシステムよりも高速で、awkお使いのコンピュータに少しの空き容量を提供しますが、データ処理が説明のように集中している場合は、専用のデータベースに切り替えると最良の結果が得られることに注意してください。 SQLite、MySQL...


awk '{ if (/^[^0-9]/) { next }              # Skip lines which do not hold key values
       if (FNR==NR) { main[$0]=1 }          # Process keys from file "mainfile"
       else if (main[$0]==0) { keys[$0]=1 } # Process keys from file "keys"
     } END { for(key in keys) print key }' \
       "mainfile" "keys" >"keys.not-in-main"

# For 6 million lines in "mainfile" and 10 thousand keys in "keys"

# The awk  method
# time:
#   real    0m14.495s
#   user    0m14.457s
#   sys     0m0.044s

# The comm  method
# time:
#   real    0m27.976s
#   user    0m28.046s
#   sys     0m0.104s

答え3

はい、必ずデータベースを使用してください。このタイプの作業用に設計されています。

答え4

データが多すぎる場合は、データベースに切り替える必要があります。同時に、適切なパフォーマンスに近づけるために必要なことは、file1各キーを個別に検索しないことです。grep一度に除外されていないすべてのキーを抽出するには、一度実行してください。キーを含まない行も返されるため、grepフィルタリングされます。

grep -o '[0-9]\{12\}' file2 |
grep -Fxv -f - file1 |
grep -vx '[0-9]\{12\}' >file3

-Fx文字通り行全体を検索することを意味します。-f -標準入力からパターンリストを読むことを意味します。)

関連情報