特定の文字列と次の行を含む行を削除します


71

私はこれを使用します

cat foo.txt | sed '/bar/d'

barファイル内の文字列を含む行を削除します。

ただし、これらの行とその直後の行を削除ます。好ましくでsedawkまたはMINGW32で利用できる他のツール。

それは私が得ることができるものの逆のようなものだgrep-Aし、-Bマッチした行の前/後に一致した行だけでなく、ラインを印刷します。

それを達成する簡単な方法はありますか?


2
情報提供のみ:エントリが2行であるログを分析しています。そのため、パターンに一致するエントリを見つけて、次の行と同様に削除します。したがって、連続するマッチラインを処理する必要はありませんが、とにかく回答の完全性に感謝します!
jakub.g

回答:


75

GNU sed(組み込みLinuxまたはCygwin)を使用している場合:

sed '/bar/,+1 d'

bar2行連続している場合、2行目は分析せずに削除されます。たとえば、3行のファイルbar/ bar/があるfoo場合、そのfoo行は残ります。


1
長さのための+1 :)私の特定の例では、連続したbars がないので、これは覚えやすいです。
jakub.g

11
sed '/bar/d'次の行ではなく「特定の文字列を含む行を削除する」だけの場合。
AJP

数学の後にすべての行を削除したい場合はどうなりますか?
Pandya

1
@Pandyaそれは違います。あなたは、例えば使用することができますsed '/math/q'
ジル・

1
@AKあなただけ一致する行を削除したい場合は、それも簡単です:sed '/bar/d'
ジル・

16

bar連続した行で発生する可能性がある場合は、次を実行できます。

awk '/bar/{n=2}; n {n--; next}; 1' < infile > outfile

上記の2行を、一致する行を含めて削除する行数で変更することにより、2行以上を削除するように適合させることができます。

そうでない場合、それは簡単で行うのsed@MichaelRollinsのソリューションまたは:

sed '/bar/,/^/d' < infile > outfile

AWK溶液中の他のプラスは、私が交換することができるということです/bar//bar|baz|whatever/。ではsedその構文動作するようには思えません。
jakub.g

@ jakub.g、私はGNU sedを持っています(現在v4.4)。他の人についてはわかりません。私が知っているのは、デフォルトで「基本的な」正規表現構文を使用していることです。これがあなたの例がうまくいかなかった理由です。目的を達成するには、各垂直線の前にバックスラッシュを置くか、sed「拡張」正規表現の使用を要求できます。詳細はこちら:gnu.org/software/sed/manual/html_node/…。これgrepも同様に適用されることに注意してください。これが私自身の実例です:echo $'0a\n1b\n2c' | sed '/0a\|1b/d'
ビクターヤレマ

12

私はsedに堪能ではありませんが、awkでそれを行うのは簡単です:

awk '/bar/{getline;next} 1' foo.txt 

awkスクリプトは次のように読み取ります。barを含む行については、次の行を取得し(getline)、その後のすべての処理をスキップします(next)。最後の1パターンは、残りの行を印刷します。

更新

コメントで指摘されているように、上記の解決策は連続して機能しませんでしたbar。以下は修正されたソリューションであり、それを考慮に入れています。

awk '/bar/ {while (/bar/ && getline>0) ; next} 1' foo.txt 

すべての/ bar /行をスキップするために読み続けています。


1
grep -A100%を複製するには、任意の数の連続するbar行を正しく処理する必要もあります(ブロック全体とその後の1行を削除することにより)。
jw013

7

これを実現するには、sedのスクリプト機能を使用する必要があります。

$ sed -e '/bar/ { 
 $!N
 d
 }' sample1.txt

サンプルデータ:

$ cat sample1.txt 
foo
bar
biz
baz
buz

「N」コマンドは、入力の次の行をパターンスペースに追加します。これは、パターンマッチ(/ bar /)の行と組み合わせて、削除する行になります。その後、「d」コマンドを使用して通常どおりに削除できます。


コンソールで改行を入力するにはどうすればよいですか?または、これはスクリプトのみですか?
jakub.g

@ jakub.g:GNUとはsedの:sed -e '/bar/{N;d}' sample1.txt
サイラス

2

一致の直後の行を削除する必要がある場合、sedプログラムは連続した一致を考慮する必要があります。つまり、一致する一致の後に続く行を削除する場合は、おそらくその後の行も削除する必要があります。

簡単に実装できますが、少し後を見る必要があります。

printf %s\\n     0 match 2 match match \
                 5 6 match match match \
                 10 11 12 match 14 15  |
sed -ne'x;/match/!{g;//!p;}'

0
6
11
12
15

読み込まれた各行のホールドスペースとパターンスペースを交換することで機能します。そのため、毎回最後の行を現在の行と比較できます。したがってsed、行を読み取ると、そのバッファーの内容が交換されます。その場合、前の行は編集バッファーの内容になり、現在の行は保留スペースに入れられます。

そのsedため、前の行でと一致するかどうかを確認し、見つからないmatch場合!{関数内の2つの式}が実行されます。sed意志g現在のラインが保留とパターンスペースの両方に続いている意味- -そしてそれはなりパターンスペース上書きしらホールドスペース//の最も最近コンパイルされた正規表現にマッチしていないか確認を- match-そしてもしそれがないmatchことをさprinted。

これは、そうでない場合は行のみが印刷されることを意味し、直前の行にはありません。また、esのシーケンスの不必要なスワップも無視します。match matchmatch

あとで発生する任意の行数を削除できるバージョンmatchが必要な場合は、もう少し作業が必要になります。

printf %s\\n    1 2 3 4 match  \
                match match 8  \
                9 10 11 12 13  \
                14 match match \
                17 18 19 20 21 |
sed -net -e'/match/{h;n;//h;//!H;G;s/\n/&/5;D;}' -ep

... 5を、削除する行数(一致した行を含む)に置き換えます...


1
2
3
4
12
13
14
21
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.