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

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

私はこれを使う

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

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

しかし、この行を削除したいです。そしてすぐ次の行。 MinGW32で利用可能な他のツールを使用することsedをお勧めします。awk

これは、一致する行と一致する行の前後の行をgrep印刷できる場所とは反対です。-A-B

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

答え1

GNU sed(組み込みのLinuxまたはCygwin)がある場合:

sed '/bar/,+1 d'

bar行に2つの行がある場合は、2番目の行を解析せずに削除します。たとえば、bar// 3行のファイルがある場合、その行barfoo保持fooされます。

答え2

bar連続した行に表示できる場合は、次のようにできます。

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

上記の2を削除する行数(一致する行を含む)に変更して2つ以上の行を削除する場合に適用できます。

そうでなければ簡単にsedできます@MichaelRollinsのソリューションまたは:

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

答え3

私はsedにあまり慣れていませんが、awkではこれを簡単に実行できます。

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

awkスクリプトの内容は次のとおりです。 barを含む行に対して次の行を取得し、その後のすべての処理をスキップします。最後の1パターンは残りの行を印刷します。

修正する

コメントで指摘したように、上記のソリューションは隣接するソリューションでは機能しませんbar。以下は、これを考慮した修正ソリューションです。

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

それでは、すべての/bar/行をスキップして読み続けます。

答え4

一致のすぐ次の行を削除する必要がある場合は、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

読み出された各ラインについてホールド空間とパターン空間を交換することによって動作するので、毎回最後のラインを現在のラインと比較することができる。したがって、sed1行を読み取ると、対応するバッファの内容が置き換えられます。前の行は編集バッファーの内容で、現在の行は予約済みスペースに配置されます。

sed前の行に一致するものがあることを確認してください。match、見つからない場合は、関数!で両方の式を実行します。パターンスペースを上書きして予約済みスペースを設定します。つまり、現在の行は予約済みスペースとパターンスペースの両方にあります。次に、最後にコンパイルされた正規表現と一致することを確認します。{}sedg//match- もしそれ確かにmatch印刷されましたp

これは、行が存在しない場合にのみ印刷されることを意味します。match そして直前の行にはその内容はありません。match。また、不要なシーケンス交換を放棄します。matchはい。

必要に応じて以下から削除できます。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

関連情報