逆方向にgrepして「前」および「後」の行を除外する方法

逆方向にgrepして「前」および「後」の行を除外する方法

次のトピックを含むテキストファイルを検討してください。

aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
iii

パターン(例えばfff)が与えられたら、上記のファイルをgrepして出力を取得したいと思います。

all_lines except (pattern_matching_lines  U (B lines_before) U (A lines_after))

たとえば、およびのB = 2場合、A = 1パターン=の出力は次fffのようになります。

aaa
bbb
ccc
hhh
iii

grepや他のコマンドラインツールを使用してこれを行うにはどうすればよいですか?


私が試したときに注意することは次のとおりです。

grep -v 'fff'  -A1 -B2 file.txt

私は欲しいものを手に入れることができませんでした。代わりに、私は次のようになります。

aaa
bbb
ccc
ddd
eee
fff
--
--
fff
ggg
hhh
iii

ベストアンサー1

gnu grepとを使用して除外したいファイルの部分を正確に印刷できますが、行番号を印刷するスイッチを追加して-A出力形式を指定し、コマンドスクリプトに渡してその行を削除します。-B-nsed

grep -n -A1 -B2 PATTERN infile | \
sed -n 's/^\([0-9]\{1,\}\).*/\1d/p' | \
sed -f - infile

grepこれは、以下を介して渡されるスキーマファイルにも適用されます。-f例:

grep -n -A1 -B2 -f patterns infile | \
sed -n 's/^\([0-9]\{1,\}\).*/\1d/p' | \
sed -f - infile

3つ以上の連続した行番号を範囲に縮小して、たとえば...代わりに使用すると少し最適化される可能性があると思います2,6dが、2d;3d;4d;5d;6d入力に一致するものがいくつかあれば実行する価値はありません。



行の順序を維持せずに速度が遅くなる他の方法は次のとおりですcomm

comm -13 <(grep PATTERN -A1 -B2 <(nl -ba -nrz -s: infile) | sort) \
<(nl -ba -nrz -s: infile | sort) | cut -d: -f2-

commソートされた入力が必要です。つまり、行の順序は最終出力に保持されません(ファイルがすでにソートされていない場合)。したがって、nlソートする前に行番号を付け、comm -13一意の行のみを印刷するために使用されます。2番目のファイル次に、cut追加された部分(nl例:最初のフィールドと区切り文字:)を削除します
join

join -t: -j1 -v1 <(nl -ba -nrz -s:  infile | sort) \
<(grep PATTERN -A1 -B2 <(nl -ba -nrz -s:  infile) | sort) | cut -d: -f2-

おすすめ記事