web-dev-qa-db-ja.com

最速のgrep

grepをできるだけ速くするためのヒントがあるかどうかを知りたい。できるだけ早く検索するためのテキストファイルのかなり大きなベースがあります。私はそれらをすべて小文字にしたので、-iオプション。これにより、検索が非常に高速になります。

また、-Fおよび-Pモードはデフォルトよりも高速です。検索文字列が正規表現(単なるプレーンテキスト)でない場合は前者を使用し、正規表現が関係する場合は後者を使用します。

grepを高速化した経験はありますか?特定のフラグ(Linux CentOSを使用)を使用してゼロからコンパイルしたり、特定の方法でファイルを整理したり、何らかの方法で検索を並列にしたりできますか?

80
pistacchio

GNU parallel を試してください。これには grepでの使用方法の例 が含まれます。

grep -rはディレクトリを再帰的に検索します。マルチコアCPUでは、GNU parallelはこれを高速化できます。

find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}

これにより、コアあたり1.5ジョブが実行され、grepに1000個の引数が与えられます。

大きなファイルの場合、--pipeおよび--block引数を使用して、入力をいくつかのチャンクに分割できます。

 parallel --pipe --block 2M grep foo < bigfile

また、SSHを介して複数の異なるマシンで実行することもできます(パスワードを回避するには、ssh-agentが必要です)。

parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile
104
Chewie

非常に大きなファイルを検索する場合は、ロケールを設定すると本当に役立ちます。

GNU grepは、UTF-8を使用する場合よりもCロケールを使用した場合の方がはるかに高速です。

export LC_ALL=C
70
daveb

Ripgrepは、現在最速であると主張しています。

https://github.com/BurntSushi/ripgrep

デフォルトで並列処理も含む

 -j, --threads ARG
              The number of threads to use.  Defaults to the number of logical CPUs (capped at 6).  [default: 0]

READMEから

Rustの正規表現エンジンの上に構築されています。 Rustの正規表現エンジンは、有限オートマトン、SIMD、および積極的なリテラル最適化を使用して、検索を非常に高速にします。

12
rado

どうやら--mmapを使用すると、一部のシステムで役立ちます。

http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html

5
Sandro Pasquali

厳密にはコードの改善ではありませんが、2,000,000個のファイルに対してgrepを実行した後に役立つことがわかりました。

安価なSSDドライブ(120GB)に操作を移動しました。約100ドルで、大量のファイルを定期的に処理する場合、手頃な価格のオプションです。

4
the wanderer

どのファイルに文字列が含まれているかを気にしない場合は、readinggrepping2つのジョブに分割します。これは、grepを何度も(小さなファイルごとに1回)生成するのにコストがかかる可能性があるためです。

  1. 非常に大きなファイルが1つある場合:

    parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>

  2. 多くの小さな圧縮ファイル(inodeでソート)

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>

スループットを最大にするため、通常はファイルをlz4で圧縮します。

  1. 一致するファイル名のみが必要な場合:

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}

3
Alex V

Sandroの回答に基づいて、私は彼が提供したリファレンスを参照しました here BSD grep vs. GNU grep。私の簡単なベンチマークの結果は、次のとおりです。GNU grepは、はるかに高速です。

したがって、元の質問「最速のgrep」に対する私の推奨事項:BSD grep(MacOSのデフォルトなど)ではなくGNU grepを使用していることを確認してください。

2
Chris

私は個人的にgrepの代わりにag(シルバーサーチャー)を使用しています。これはずっと高速です。また、並列ブロックやパイプブロックと組み合わせることができます。

https://github.com/ggreer/the_silver_searcher

更新:私は https://github.com/BurntSushi/ripgrep を使用するようになりました。これは、ユースケースによってはagよりも高速です。

2
Jinxmcg

1つの大きなファイルでgrepを使用して(特にパターンを変更するために)grepを使用して高速に検索できることの1つは、split + grep + xargsを並列フラグとともに使用することです。例えば:

My_ids.txtという名前の大きなファイルで検索するIDのファイルがあるBigf​​ileの名前bigfile.txt

ファイルをパーツに分割するには、splitを使用します。

# Use split to split the file into x number of files, consider your big file
# size and try to stay under 26 split files to keep the filenames 
# easy from split (xa[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]

# Now use split files + xargs to iterate and launch parallel greps with output
for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done
# Here you can tune your parallel greps with -P, in my case I am being greedy
# Also be aware that there's no point in allocating more greps than x files

私の場合、これにより17時間の仕事が1時間20分の仕事になりました。ここには効率に何らかのベルカーブがあり、利用可能なコアを超えることは何の役にも立ちませんが、上記の私の要件に対する上記のコメントよりもはるかに優れたソリューションでした。これには、ほとんどの(Linux)ネイティブツールを使用する際に、スクリプトと比較して利点があります。

1
user6504312

cgrepが利用可能であれば、grepよりも桁違いに高速です。

0
xhtml

MCE 1.508には、多くのCバイナリをサポートするデュアルチャンクレベルの{file、list}ラッパースクリプトが含まれています。 agrep、grep、egrep、fgrep、およびtre-agrep。

https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep

https://metacpan.org/release/MCE

-iを高速で実行する場合、小文字に変換する必要はありません。 --lang = Cをmce_grepに渡すだけです。

出力順序は保持されます。 -nおよび-bの出力も正しいです。残念ながら、このページで言及されているGNUパラレルの場合はそうではありません。 GNU Parallelがここで動作することを本当に望んでいました。さらに、mce_grepは、バイナリを呼び出すときにサブシェル(sh -c/path/to/grep)をnotします。

別の代替手段は、MCEに含まれているMCE :: Grepモジュールです。

0
Mario Roy

元のトピックからのわずかな逸脱:googlecodesearchプロジェクトのインデックス付き検索コマンドラインユーティリティは、grepよりもはるかに高速です。 https://github.com/google/codesearch

コンパイルしたら( golang パッケージが必要です)、フォルダーのインデックスを作成できます:

# index current folder
cindex .

インデックスは~/.csearchindexの下に作成されます

これで検索できます:

# search folders previously indexed with cindex
csearch eggs

私はまだ色分けされた一致を得るためにgrepを通して結果をパイプしています。

0
ccpizza