
grepを使用して入れ子になったディレクトリ構造内の次のファイルを検索する方法みんな私の検索パターンに含まれる単語は何ですか?
複数の単語を含むファイルを見つけるためにgrepを使用したいと思います。 foo barとbahを試してみましょう。できますが、grep -rl foo |xargs grep -rl bah| ...etc
より簡単な方法はありますか?検索する文字列ファイルとして-Fを使用できることを知っていますが、まだOR演算子(和集合)を使用して文字列を検索し、AND演算子(交差)を使用する必要があると思います。
答え1
find
+awk
解決策:
find . -type f -exec awk '/\<foo\>/{ p1=1 }/\<bar\>/{ p2=1 }/\<bah\>/{ p3=1 }
p1 && p2 && p3{ print FILENAME; exit }' {} +
awk
プログラムの詳細:
/\<foo\>/{ p1=1 }/\<bar\>/{ p2=1 }/\<bah\>/{ p3=1 }
- それぞれの必須パターンが見つかったら、対応するフラグを設定します。p1 && p2 && p3
- すべてのパターンが見つかった場合:print FILENAME
- 現在の印刷ファイル名/ファイルパスexit
- スクリプト実行直ちに終了
答え2
私の答えは@RomanPerekhrestの答えと似ています。主な違いは、レコード区切り記号()を入力内のどの項目とも一致しない項目(たとえば)に設定することで、入力全体をawk
一度に処理できるという事実を利用することです。つまり、ファイル全体を飲み込み、1つの文字列であるかのように検索します。RS
^$
例えば
find . -type f -exec \
awk -v RS='^$' '/foo/ && /bar/ && /baz/ { print FILENAME }' {} +
.
現在のディレクトリ()に含まれているすべてのファイルが一覧表示されます。みんな正規表現foo
、bar
およびbaz
。正規表現の一部または全部を完全な単語として扱う必要がある場合は、単語境界アンカーで囲みます\<
(\>
例:)\<foo\>
。
また、各ファイルを一度フォークしないため、より速く実行されますawk
。代わりに、コマンドラインバッファに収まるほど多くのawk
ファイル名引数を使用して実行されます(最新のシステムでは通常128Kまたは1または2M文字)。ではありません。 。find
awk
メモ:これには正規表現がawk
許可されているバージョンが必要です。RS
バラよりawkのフルルックモード?他のバージョンのawkで制限された形式の「slurpモード」を実装する方法の詳細と例については、読んでください。
また注:これにより、メモリ内の各ファイルの内容全体が一度に1つずつ読み込まれます。数十ギガバイト以上のログファイルなど、非常に大きなファイルの場合は、使用可能なRAMまたはRAM + SWAPを超える可能性があります。これが起こる可能性はほとんどありませんが、もしそうなら、深刻な問題が発生する可能性があります(たとえば、LinuxでRAMとSWAPが不足すると、カーネルはランダムプロセスを終了し始めます)。
答え3
このような論理ANDの場合、通常は次のものを使用しますawk
。
awk '/foo/ && /bar/ && /bah/ { print }' /path/to/file
答え4
grep
以下でGNUを使用してください-P
(パール互換性)オプションと肯定的な予測正規表現(?=(regex))
1行またはファイル全体で順序に関係なく単語を検索し、現在のディレクトリから始まるすべてのファイルで繰り返し単語を見つけます。
grep -rlP '(?s)(?=.*?\bfoo\b)(?=.*?\bbar\b)(?=.*?\bbah\b)' .
(?s)
これはDOTALL修飾子で、次のことを許可します。指す\newlinesを一致させるために(.|\n)*?
Tooとbetweenwordsを使用してください[\s\S]*?
。at
\bWORD\b
;\b
は単語境界アンカーポイントです。
次のように入力します。
==> file1 <== foo here and bar bah and of file1 ==> file2 <== foo then bar and bah ==> file3 <== foo foobarbah ba ==> file4 <== this is foo bar bahh bah
出力は次のとおりです
./file1
./file2
./sub-dir/file4