grepを使用して、パターンを照合し、別のパターンを反転照合するにはどうすればよいですか?


11

を使用してgrep、パターンに一致し、別のパターンに一致しないすべての行を選択します。私は、単一の呼び出しを使用することができるようにしたいgrep、私が使用できるように、--after-contextオプション(または--before-context、あるいは--context)を。

-vオプションをgrep使用して渡すすべてのパターンが無効になるため、ここでは実行できません-e

一致needleする行を無視してignore me、次のコンテキストの1行で一致する行を探します。

これが私の入力ファイルです:

one needle ignore me
two
three
four needle
five

私が欲しい出力は:

four needle
five

ご覧のとおり、この単純な解決策は機能しません。

$ cat file | grep --after-context=1 needle | grep -v 'ignore me'
two
---
four needle
five

回答:


10

GNU grepを使用している場合は、否定構造を持つPerl正規表現を使用できます。

grep -A1 -P '^(?!.*ignore me).*needle'

GNU grepがない場合は、その前後のコンテキストオプションをawkでエミュレートできます

awk -v after=3 -v before=2 '
/needle/ && !/ignore me/ {
    for (i in h) {
        print h[i];
        delete h[i];
    }
    until = NR + after;
}
{
    if (NR <= until) print $0; else h[NR] = $0;
    delete h[NR-before];
}
END {exit !until}
'

8

GNU を使用しているようです。GNU grepを使用すると、--perl-regexフラグを渡してPCREをアクティブにしてから、以下の例のように否定先読みアサーションを提供できます。

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five

ノートの主なものは、ここではそれがある(?:(?!STRING).)*にあるSTRINGよう[^CHAR]*にありますCHAR


1_CR ...サー... @それは素晴らしいです..:Pの何かsmilerへack
ラーフルパティル

@RahulPatil。:-)、はい、GNU grepはそれで十分です。
iruvar 2013年

それは私が望むものではありません。「無視」が「針」の前でも後でも機能してほしい。
Flimm 2013年

@RahulPatil、ありがとう、私は最新バージョンでそれを修正しました
iruvar '17

非常に便利。特に、コンテキストに一致する行を除外したいがパターンの特定の部分がないgrepの場合。元の質問に近いがまったく同じではない。
gaoithe 2016年

2

マルチラインIOをより適切に処理するため、代わりにawkを使用することをお勧めします。いずれか1)管をGNUのAWKの結果--\nレコードセパレータ、又は2) AWKにマッチングのすべてを行います。

オプション1

<file grep -A1 needle | awk '!/ignore me/' RS='--\n' ORS='--\n'

出力:

four needle                                                                                  
five
--

このオプションは、最初の行と比較するためだけにignore me、レコード全体を検索し、設定しFS=1、照合し$1ます。

オプション2

<file awk 'a-- > 0; $0 ~ re1 && $0 !~ re2 { print $0; a=after }' re1=needle re2='ignore me' after=1

ignore meファイルに複数ありますか、awkは機能しません
Rahul Patil

@RahulPatil:質問を言い換えたり、詳細を追加したりできますか?私はあなたが何を求めているのか理解できません。
2013年

@Thosは、この入力ファイルpaste.ubuntu.com/6252860で
Rahul Patil

@RahulPatil:私の言っているとおり、オプション1--\nでは、一致する各グループの間に区切り文字があると想定しています。グループが互いに隣接している場合は、区切り文字はありません。隣接するグループの処理方法はタスク固有であるため、これは必ずしも間違っているとは限りません。オプション2はセパレーターに依存せず、影響を受けません。
2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.