次のトピックを含むテキストファイルを検討してください。
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
-n
sed
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-