空白を含むgrep出力でxargs grepを実行する方法は?

空白を含む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-0xargsgrep

それとも私が完全に間違った方向に行っているのでしょうか?素直に言えばfind私にとっては理解grepできますが、xargs grep同じ結果を生成する他の方法にも開いています。

答え1

おそらく同様のものを使うことができます(gnu grepの場合)。

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

人々はgrep

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

空の区切り記号のオプションも参照してください。

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

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

答え2

多くの困難を経験する必要がある場合、とにかくxargsの効率は失われます。おおよその回避策は次のとおりです。

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

ファイル名の空白の問題が発生するたびに、答えは変数に二重引用符でした。

答え3

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 …

次の内容を含むファイルにも適用する必要があります。改行文字彼らの名前で。

そして、完全な正規表現の強力な機能が必要な場合に使用できます-regex

答え4

これは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を使用すると、呼び出しを削除してperlxargs -0 …のように変更できます。xargs -d "\n" …

GNUはありませんかperl?試してawk '{printf "%s%c", $0, 0}'みてください。

関連情報