grepを使用してファイルから複数の文字列を検索する方法(クロスポイント検索)

grepを使用してファイルから複数の文字列を検索する方法(クロスポイント検索)

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 }' {} +

.現在のディレクトリ()に含まれているすべてのファイルが一覧表示されます。みんな正規表現foobarおよびbaz。正規表現の一部または全部を完全な単語として扱う必要がある場合は、単語境界アンカーで囲みます\<\>例:)\<foo\>

また、各ファイルを一度フォークしないため、より速く実行されますawk。代わりに、コマンドラインバッファに収まるほど多くのawkファイル名引数を使用して実行されます(最新のシステムでは通常128Kまたは1または2M文字)。ではありません。 。findawk

メモ:これには正規表現が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

関連情報