ディレクトリとそのサブディレクトリ内のすべてのファイルで特定の文字列を含む行を検索したいのですが、その直後の行に別の特定の文字列を含む結果を除外したいと思います。
たとえば、これは次のとおりです。
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に、一致するものが見つかった場合は前の行も削除する必要があることを伝える方法はありますか?または、他の方法でこれを達成する方法はありますか?
パフォーマンスは私の主な関心事ではありません。ただし、コマンドが比較的覚えやすい場合は便利です。
p
erl c
ompatible r
egular e
xpressions grep
を使用できます。
$ pcregrep -M '(searchString.*\n)(?!.*excludeString)' file
foo2 searchString bar
foo3 searchString bar
foo4 searchString bar
searchString
の後に任意のchar.
を検索し、0回以上*
を繰り返し、その後に改行\n
のみが続く場合は- not(?!
)パターン.*excludeString
その隣。複数行に一致させるために、オプション-M
があります。
sed
の場合:
sed '/searchString/!d;$!N;/\n.*excludeString/!P;D' infile
使い方:
/searchString/!d
は、searchString
と一致しない場合はその行を削除し、新しい行を読み込み、コマンドサイクルを最初からやり直します(つまり、残りのコマンドは実行されなくなります)。searchString
と一致する場合、sed
は$!N;/\n.*excludeString/!P;D
を実行します [〜#〜] here [〜#〜] どのように機能するか;違いは、ここでは、\n
ewline文字の後にパターンexcludeString
を探しているため、searchString
とexcludeString
の両方に一致する行が出力されることです。 excludeString
に一致する行が続かない; searchString
とexcludeString
の両方に一致する行がない場合(つまり、既知の入力)、\n.*
の部分を削除して実行できます。sed '/searchString/!d;$!N;/excludeString/!P;D' infile