パターンA(iwant)を含むファイルをgrepしたいのですが、パターンB(idonwant)を含むファイルを除外したいと思います。
例:
read -p "...what are you looking for: " iwant
read -p "...what should not be included: " idontwant
iwant="blue car"
idontwant="red car"
次のようなファイルがあるとしましょう。
-rw-rw-r--. 1 terpentin terpentin 45 Jun 8 16:04 blue.car
-rw-rw-r--. 1 terpentin terpentin 44 Jun 8 16:05 mixed.car
-rw-rw-r--. 1 terpentin terpentin 40 Jun 8 16:04 red.car
find . -type f -print -exec cat {} \;
./mixed.car
blue car
red car
blue car
./red.car
red car
red car
red car
./blue.car
blue car
blue car
blue car
その結果、「./blue.car」ファイルのみを取得することはどのように可能ですか?
元のコンテンツは何百もの長いテキストファイルで構成されているので、できるだけリソースを節約することが重要でした。
答え1
使用
find . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -print
または
find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
- コマンドの用語(時々「述語」とも呼ばれる)
find
の特徴は次のとおりです。テスト(例-type f
:)と行動(例:-print
と-delete
)。マニュアルページで-exec
両方を把握するのは難しいかもしれません。行動そして テスト。だから探す。 -type f -mtime -30 -name '*.txt' -読みやすいサイズ +5テスト6 テスト7 テスト8…
すべての基準を満たす(指定されたすべてのテストを満たす)ファイルで検索範囲を継続的に絞り込みます。探す。 -実現するコマンド1{} ';' -実現するコマンド2{} ';' -実現するコマンド3{} ';'
すべてのコマンドが成功したファイルを探します。 - すべての
find
テストは前に付けて無効化(反転)できます!
。したがってfind . ! -type d
、通常のファイル、シンボリックリンク、名前付きパイプ、ソケット、およびデバイスファイル(ディレクトリ以外のすべて)を見つけることができます。 ! -exec grep …
と同じではありません-exec grep -v …
。-exec grep -v …
一致しない行が1つ以上あるファイルが検索されます。! -exec grep …
ファイルが見つかる場所いいえ行が一致します。- オプション
-q
はgrep
の正式な同義語ですが、--quiet
次のことも意味します。クイック。出力を書き込まず(該当する場合はエラーメッセージを除く)、一致が見つかると終了します。各ファイルは最後まで読みません。すべてマッチ。 (もちろん、ファイルに一致するものがない場合は、grep
内容全体を読む必要があります。) - だから(長い話を短く) そのファイルを探すコマンド
grep -q "$iwan" 文書
成功grep -q "$idontwant"文書
失敗します(前に追加したため!
)。 - 両方のコマンドは機能的に同じですが、パフォーマンスが異なる場合があります(つまり、実行時間が異なる場合があります)。検索文字列を含むファイルが数個しかない場合、
探す。 -type f -exec grep -q "$iwant" {}';' -exec grep -q "$idontwant" {}';'
grep "$iwant"
ほとんどのファイルが削除されるため、速度が速くなります。多くのファイルにこれら2つの文字列が含まれている場合探す。 -fと入力してください! -exec grep -q "$idontwant" {}';' -exec grep -q "$iwant" {}';'
! grep "$idontwant"
ほとんどのファイルが削除されるため、速度が速くなります。
答え2
GNU grep
正規表現とgrepオプションを賢く選択してファイル名抽出を実行できます。
$ grep -lzPsr '(?s:(?=.*blue)(?!.*red))' .
ファイル全体が1行として処理されるslurpモード(-z)でgrepを実行します。
-l は、正規表現に一致するファイルの名前をリストします。
-r は、現在のディレクトリ内のすべてのファイルに対して繰り返し実行されます。
-sは警告を表示せずにgrepをサイレントにします。
正規表現は、「はい」と答えるためにファイルに青があり、赤がないかどうかを探します。
-P は pcre 正規表現を利用できるように grep で Perl 正規表現エンジンを呼び出します。