If any line immediately following a match should be removed then your sed
program will have to consider consecutive matches. In other words, if you remove a line following a match which also matches, then probably you should remove the line following that as well.
It is implemented simply enough - but you have to look-behind a little.
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
It works by swapping hold and pattern spaces for each line read in - so the last line can be compared to the current each time. So when sed
reads a line it exchanges the contents of its buffers - and the previous line is then the contents of its edit buffer, while the current line is put in hold space.
So sed
checks the previous line for a match to match
, and if its !
not found the two expressions in the {
function }
are run. sed
will g
et the hold space by overwriting the pattern space - which means the current line is then in both the hold and pattern spaces - and then it will //
check it for a match to its most recently compiled regular expression - match
- and if it does not match
it is p
rinted.
This means a line is only printed if it does not match
and the immediately previous line does not match
. It also foregoes any unnecessary swaps for sequences of match
es.
If you wanted a version that could drop an arbitrary number of lines occurring after a match
it would need a little more work:
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
...replace the 5 with the number of lines (including the matched line) that you would like to remove...
1
2
3
4
12
13
14
21