正規表現に基づいてファイルを検索してから、それらのファイルのコンテンツを検索しようとしています。たとえば、私は次のようなものを持っています
#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
は私には理にかなっていますが、同じ結果が得られる他のアプローチを受け入れることはできます。
おそらくこのようなものを使用してください(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などのコマンドで使用して、任意のファイル名を処理できます。
たくさんのフープを飛び越えなければならない場合、xargsの効率はとにかく失われます。これは、次のような大まかな回避策です。
find . -iname "*.cpp" | grep "<pattern>" | while read -r x; do grep exa "$x"; done
ファイル名にスペースが含まれている問題に遭遇するたびに、答えは変数の二重引用符です。
すべてのファイル名フィルタリングを行うには、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
を使用できます。
これは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}'
をお試しください。