特定の文字列を含む行のディレクトリとそのサブディレクトリ内のすべてのファイルを検索したいのですが、次の行に他の特定の文字列を含む結果を除外したいと思います。
たとえば、次のようになります。
foo1 searchString bar
foo1 excludeString bar
foo2 searchString bar
something else
foo3 searchString bar
foo3 excludeString bar
foo4 searchString bar
以下を返す必要があります。
foo2 searchString bar
foo3 searchString bar
foo4 searchString bar
-A
複数行を印刷して-v
結果を除外する方法を知っています。しかし、私の現在のアプローチgrep -r -A 1 "searchString" | grep -v "excludeString"
は明らかに機能しません。
一致するものが見つかったら、前の行も削除する必要があることを2番目のgrepに指示する方法はありますか?それとも別の方法でこれを達成できますか?
パフォーマンスは私の最大の関心事ではありません。コマンドが比較的覚えやすい場合は良いでしょう。
答え1
p
erl準拠のc
正規r
表現e
を使用できますgrep
。
$ pcregrep -M '(searchString.*\n)(?!.*excludeString)' file
foo2 searchString bar
foo3 searchString bar
foo4 searchString bar
ゼロ個以上の文字searchString
の後に新しい行が続く文字を検索します。.
*
\n
ただもしあればいいえ()パターンの横にあります?!
。複数行を一致させる.*excludeString
オプションがあります。-M
答え2
そしてsed
:
sed '/searchString/!d;$!N;/\n.*excludeString/!P;D' infile
仕組み:
/searchString/!d
一致しない場合は、その行を削除して新しい行をsearchString
読み取り、コマンドループを再起動します(つまり、残りのコマンドは実行されません)。- 行が一致したら
searchString
実行sed
してください$!N;/\n.*excludeString/!P;D
- 参照ここ仕組み;違いは、ここでは行が両方とも一致するようにewline文字excludeString
の後ろのパターンを探し、その後に一致する行がなければandと一致する行がなければ印刷を続けることです。既知の入力)行からその部分を削除し、次のことを実行できます。\n
searchString
excludeString
excludeString
searchString
excludeString
\n.*
sed '/searchString/!d;$!N;/excludeString/!P;D' infile