毎日約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からすべての数値を抽出してソートします。
- ファイル2からすべての数値を抽出してソートします。
comm
2番目のリストの内容だけを取得するには、ソートされたリストを実行してください。
このような:
$ 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
この回答は公開された回答に基づいています。痛み..同じ状況では、この方法(私のシステムでは)
よりも倍速です。comm
600万行メインファイルと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 -
標準入力からパターンリストを読むことを意味します。)