web-dev-qa-db-ja.com

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

私はこれを使います

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

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

ただし、これらの行は削除しますおよびその直後の行。できれば、sedawk、またはMinGW32で利用可能なその他のツールを使用することをお勧めします。

grep-A-Bを使用して一致する行だけでなく、一致する行の前/後の行も印刷できるのとは逆です。

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

77
jakub.g

GNU sed(したがって非組み込みLinuxまたはCygwin)がある場合:

sed '/bar/,+1 d'

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

barが連続する行で発生する可能性がある場合は、次のようにすることができます。

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

これは、上記の2を、一致する行を含めて削除する行数で変更することにより、3行以上を削除するように構成できます。

そうでない場合は、sed@ MichaelRollins 'solution または次のように簡単に実行できます。

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

私はsedには堪能ではありませんが、awkではそうするのは簡単です。

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

Awkスクリプトは次のように読み取ります。バーを含む行の場合、次の行を取得し(getline)、その後の処理をすべてスキップします(次)。末尾の1パターンは、残りの行を印刷します。

更新

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

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

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

12
Hai Vu

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

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

サンプルデータ:

$ cat sample1.txt 
foo
bar
biz
baz
buz

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

7
Michael Rollins

一致の直後の行を削除する必要がある場合、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は、パターンスペースを上書きしてホールドスペースをgetします。つまり、現在の行がホールドスペースとパターンスペースの両方にあることを意味します。その後、//をチェックして、最後にコンパイルされた正規表現に一致-match-そしてitが一致しない場合match一致printed。

これは、行が表示されない場合にのみ印刷されることを意味しますmatchand直前の行は表示されませんmatch =。 match esのシーケンスの不要なスワップもすべて無視されます。

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
2
mikeserv