web-dev-qa-db-ja.com

スペースがあるgrep出力でxargs grepを実行するにはどうすればよいですか?

正規表現に基づいてファイルを検索してから、それらのファイルのコンテンツを検索しようとしています。たとえば、私は次のようなものを持っています

#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp" | grep "<name regex>" | xargs grep "<content regex>"

私が実行している問題は、一部のパスにスペースが含まれているため、xargsが混乱することです。 findだけを使用している場合は、-print0引数を(xargs-0引数とともに)使用して、xargsがスペースを処理しないようにすることができます。区切り文字。 grepに似たものはありますか?

それとも、この問題に完全に間違った方法で取り組んでいますか?単純に、find to grep to xargs grepは私には理にかなっていますが、同じ結果が得られる他のアプローチを受け入れることはできます。

8
quanticle

おそらくこのようなものを使用してください(gnu grepの場合)。

grep -r 'content pattern' --include==*.cpp

男グレップ

--include = GLOBベース名がGLOBと一致するファイルのみを検索します(--excludeで説明されているワイルドカード一致を使用)。

NULL区切り文字のオプションも参照してください。

-Z、--null通常、ファイル名の後に続く文字の代わりにゼロバイト(ASCII NUL文字))を出力します。たとえば、grep -lZは各ファイル名の後にゼロバイトを出力します通常の改行の代わりに使用します。このオプションは、改行などの異常な文字を含むファイル名が存在する場合でも、出力を明確にします。このオプションは、find -print0、Perl -0、sort -z、xargs -0などのコマンドで使用できます。任意のファイル名を処理します。改行文字を含むものも含みます。

-z、--null-data入力を一連の行として扱い、各行を改行ではなくゼロバイト(ASCII NUL文字)で終了します。-Zまたは-のようにnullオプション。このオプションは、sort -zなどのコマンドで使用して、任意のファイル名を処理できます。

5
Zoredache

たくさんのフープを飛び越えなければならない場合、xargsの効率はとにかく失われます。これは、次のような大まかな回避策です。

find . -iname "*.cpp" | grep "<pattern>" | while read -r x; do grep exa "$x"; done

ファイル名にスペースが含まれている問題に遭遇するたびに、答えは変数の二重引用符です。

4
Baazigar

すべてのファイル名フィルタリングを行うには、findを使用します。のではなく

find . -name "*.cpp" | grep "foo" | xargs grep …

行う

find . -name "*.cpp" -name "*foo*" -print0 | xargs -0 grep …

あなたが少し複雑なことをしたいなら、

find . -name "*.cpp" | egrep "foo|bar" | xargs grep …

できるよ

find . -name "*.cpp" "(" -name "*foo*" -o -name "*bar*" ")" -print0 | xargs -0 grep …

これらは、名前にnewlinesが含まれているファイルでも機能することに注意してください。

また、本格的な正規表現の機能が必要な場合は、-regexを使用できます。

3
Scott

これはGNUツールがなくても機能するはずです:

#Find all C++ files that match a certain pattern and then search them
find . -name "*.cpp"  | grep "<name regex>" | Perl -pe 's/\n/\0/' \
  | xargs -0 grep "<content regex>"

Perl呼び出しは、改行をnull文字に置き換えます。これにより、xargs -0が空白ごとではなく行ごとに入力を解釈できるようになります。

GNUを使用すると、Perl呼び出しを削除し、xargs -0 …xargs -d "\n" …に変更できます

PerlもGNUも持っていませんか?代わりにawk '{printf "%s%c", $0, 0}'をお試しください。

2
Adam Katz