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


8

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

#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引数を(-0引数on と共にxargs)使用して、xargsがスペースを区切り文字として扱わないようにすることができます。同様のものはありgrepますか?

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


2
パラメータa xargsを使用して引数を配置できます。中括弧は、引数を配置する場所を示します。マニュアルは私に非難されていることを教えてくれますので、それも見てみる価値があるかもしれません。-icat sample.txt | grep "pat t ern" | xargs -i grep "{}"-i-I
dougBTV 2015年

回答:


5

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

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

男グレップ

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

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

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

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


grep -r include='*.cpp'これはfind . -name '*.cpp' -exec grep -e 'content_pattern' -- {} \;find . -name '*.cpp' | grep 'name_pattern' | xargs grep 'content_pattern'
シェルグロブで

4

たくさんのフープを飛び越えなければならない場合、xargsの効率はとにかく失われます。これは次の粗雑な作業です。

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

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


これにより、外側のgrepによって検出された各行に対してループの内側のgrepが一意に実行されます。それはかなりのオーバーヘッドです。
Adam Katz、

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


2

これは、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呼び出しができるようになりますヌル文字で改行を置き換えるxargs -0ライン単位ではなく、あたりの空白基づいて、入力を解釈します。

GNUを使用して、削除することができperl、コールをして変更xargs -0 …しますxargs -d "\n" …

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


1
一部のファイル名に改行が含まれている場合、これは正しく動作しない可能性があります(確かに珍しいことですが、不可能ではありません)。
dhag

@dhagはに関して有効なポイントがありxargs -d "\n"ます。これは非常に珍しい出来事ですが、データを制御できず、それがセキュリティリスクになるのではないかと心配している場合は、出力の期待値に注意してください。
Adam Katz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.