GNU並列処理のない大規模ファイルセットのgrepパターン

GNU並列処理のない大規模ファイルセットのgrepパターン

36コアシステムで10Mファイルのパターンをすばやく見つけたいです。これを試しました。

find . -name '*.xml' -type f | xargs  -P 20 grep "username" >> output

しかし、その間に他の結果も得ました。

これを行うより良い方法はありますか?

よろしくお願いします。

答え1

データがRAIDではなくHDDにあることを考えると、並列化によってより良いパフォーマンスが得られるかどうか疑問です。ボトルネックはCPUではなくI/Oである可能性が高いです。

LC_ALL=C grep -rwF --include='*.xml' username . > /on/some/other/disk/output

おそらくあなたが得ることができる最高に近いです。

並列化するには、次のことが必要です。

LC_ALL=C find . -name '*.xml' -type f -print0 |
  LC_ALL=C xargs -r0P20 -n 1000 grep -HFw --line-buffered username > output

4KiBより長い出力ライン(入力ライン+ファイルパス名)がないと仮定し、20本の同時grepラインが最終的にインターリーブされることに注意してください。

望むより:

もっと学ぶ。

答え2

パターンがあまりにも一般的なので、そうだと思います。通常、コマンドラインユーティリティはstderrまたは端末にエラーを出力します。出力ファイルに入ってはいけません。

答え3

このようにファイルをgreppingすると、xml検索文字列を含む行全体が返されxmlます。ファイルに改行文字がない場合は、ファイル全体の内容が返されます。 10Mファイルには「その他」がかなり多いです。

xml@Kusalanandaのコメントによると、より良いツールを使用してパーサーを強制的に使用するのはgrep良い習慣ではありませんが、主張するなら...xmlxmllint

戻り値を制限するオプションを確認して読み取り、manそれを使用して探している一致の全長を定義します。grep-oregex

username属性の場合

grep -o 'username="[^"]*"'

またはより良い

xmllint --xpath "//@username"

ノードなら、username次のようになります。

grep -o "username>[^<][^<]*"

またはより良い

xmllint --xpath "//username"

すべてのxmllintクエリに対してクエリをラップしてstring()属性またはノードテキストを抽出するだけです。

xmllint --xpath "string(//username)"
xmllint --xpath "string(//@username)"

関連情報