web-dev-qa-db-ja.com

grepよりも高速なものはありますか?

私はgrepよりも高速なツール、多分マルチスレッドのgrep、または類似のものを探しています...私はたくさんのインデクサーを探していましたが、インデックスが必要なため販売されていません...

約1億のテキストファイルがあり、完全に一致する文字列をgrepする必要があります。文字列の一致を見つけると、一致が見つかったファイル名が必要です。

ie: grep -r 'exact match' > filepaths.log

約4TBのデータで、6日前に最初の検索を開始しましたが、grepはまだ実行中です。あと12件の検索があり、これらすべてのファイル名を取得するのに2か月待つことはできません=]

以下を確認しましたが、これらのインデクサーに付属するすべての機能が必要だとは思いません。一致したファイル名が必要です...

  • dtSearch
  • テリア
  • ルセン
  • ザピアン
  • 反動
  • スフィンクス

そして、これらすべてのエンジンについて何時間も読んだ後、私の頭は回転しています。マルチスレッドのgrep lolがあったらいいのにと思います。アイデアや提案は大歓迎です。

PS:私はCentOS 6.5を実行しています

編集:マルチスレッドのgrepを検索すると、いくつかの項目が返されます。私の質問は、マルチスレッドのgrepが私がやっていることに最適なオプションですか?

EDIT2:少し調整した後、これが私が思いついたものであり、通常のgrepよりもはるかに高速になっていますが、それでも高速であることを願っています...私はディスクIOの待機を監視しています、私はさらに微調整を行うかもしれませんが、defはまだ提案に興味があります=]

find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string'
7

grepはI/Oバウンドです。つまり、その速度は、検索しているファイルを読み取ることができる速度によって決まります。複数の検索を並行して実行すると、ディスクI/Oをめぐって互いに競合する可能性があるため、速度が大幅に向上しない場合があります。

ファイルで見つかった実際の一致ではなく、一致するファイル名のみが必要な場合は、-lフラグを指定してgrepを実行する必要があります。このフラグにより​​、grepは一致するファイル名のみを出力し、一致する行は出力しません。ここでの値は、一致が見つかると、grepがファイルの検索を停止できるようになるため、grepが実行する必要のある作業量を減らすことができます。

正規表現ではなく固定文字列を検索する場合は、fgrepではなくgrepを使用してみてください。 Fgrepは、固定文字列を検索するgrepの変形であり、固定文字列の検索は、正規表現検索を実行するよりも高速です。最新のバージョンのgrepはおそらく固定文字列検索を最適化するのに十分なほどスマートであるため、これによって改善が見られる場合と見られない場合があります。

複数の検索を並行して実行したい場合は、シェルユーティリティを使用して実行できます。 1つの方法は、ファイル名のリストを作成し、それを複数の部分に分割し、リストごとに個別にgrepを実行することです。

find /path/to/files -type f -print | split -l 10000000 list.
for file in list.*; do
    grep -f ${file} -l 'some text' > ${file}.out &
done
wait
cat $*.out > filepaths.log
rm list.*

これはfindを使用してファイルを検索し、ファイル名のリストを1000万のグループに分割し、各グループに対して並列にgrepを実行します。 grepsの出力はすべて最後に結合されます。これは一般的な名前のファイルで機能するはずですが、たとえば、名前に改行が含まれているファイルでは失敗します。

別のアプローチでは、xargsを使用します。まず、バックグラウンドでgrepを実行する簡単なシェルスクリプトを記述する必要があります。

#!/bin/bash
grep -l 'search text' "$@" >> grep.$$.out &

これは、スクリプトの引数として指定されたファイルのリストに対してgrepを実行し、プロセスのPIDにちなんで名付けられたファイルに結果を書き込みます。 grepプロセスはバックグラウンドで実行されます。

次に、次のようにスクリプトを実行します。

find /path/to/files -type f -print0 | xargs -0 -r /my/grep/script
[ wait for those to finish ]
cat grep.*.out > filepaths.log
rm grep.*.out

この場合、xargsはファイル名をグループにまとめ、グループごとに1回スクリプトを実行します。スクリプトは、グループごとに1回grepのインスタンスを実行します。すべてのgrepインスタンスが終了したら、それらの出力を組み合わせることができます。残念ながら、grepインスタンスがここで終了するのを自動的に待機する賢い方法は考えられなかったので、手動で行う必要があるかもしれません。

11
Kenster

より高速なgrepが必要とする以上に、grepの複数のインスタンスを実行するスクリプトまたは小さなプログラム(つまり、4コア/ 8スレッドの最新のi7で8 x grepを並列に実行できる)を必要とするように聞こえ、出力を連結またはマージする。

そのようなスクリプトを作成する方法はまったく別の問題ですが、それが私があなたの問題を攻撃する方法です。

0
Kristian