Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SED: Delete X Lines After a Match

Tags:

macos

sed

I'm trying to delete a range using sed. The range is from a known match and the next 2 lines. Let's say I want to delete all lines that start with Don't and then the 2 lines that follow.

Please note that I am also doing substitutions in a sed command file. As such, I am avoiding using -n and /p in my solution space.

For whatever reason, I want to limit myself to one invocation of sed.

Here's my data (data.txt):

Print Me
Please Output This line
Don't Print Me and 2 more lines
This line is no good
So is this one
We should see this line
And this one, too.

Here's my expected output:

Print Me
Please Output This line
We should see this line
And this one, too.

Here's an attempted go at this:

sed -f delete_dont_plus_2.sed data.txt

With this as delete_dont_plus_2.sed:

/^Don't/,+2d

Here is my result:

sed: 1: delete_dont_plus_2.sed: expected context address

I've also tried these:

/^Don't/,/^Don't/+2d
/^Don't/,{/^Don't/+2}d

Second approach to this question:

Let's say we wanted to make this code a little more robust. Today there are 2 more lines that need to be deleted, but who knows how many lines there will be in the future. Let's say we want to delete up to, but not including We should see this line. In this variant of the question, the results are exactly the same. Again, let's consider a limited BSD sed so we cannot use an expression like /^Don't/,/^We should see this line/-1d.

Thanks!

like image 831
Mark Avatar asked Oct 24 '25 22:10

Mark


2 Answers

You're probably using a sed that doesn't support adresses in regexp,+n form. Here is a workaround for this particular case:

/^Don't/{N;N;d;}

It simply reads two more lines into the pattern space when ^Don't is found and deletes them altogether.

But anyways, I think sed is not the right tool for this, you should use awk instead. E.g:

awk '/^Don\047t/{c=2;next} !(c&&c--)' file

c.f: Printing with sed or awk a line following a matching pattern


wrt

Let's say we want to delete up to, but not including We should see this line. In this variant of the question, the results are exactly the same.

Using sed you'd need to write same RE twice:

/^Don't/,/^We should see this line/{/^We should see this line/!d;}

Using awk you don't even need REs:

awk 'index($0,"Don\047t")==1{d=1} $0=="We should see this line"{d=0} !d' file
like image 190
oguz ismail Avatar answered Oct 28 '25 03:10

oguz ismail


With GNU sed:

sed "/^Don't/,+2d" file

Output:

Print Me
Please Output This line
We should see this line
And this one, too.
like image 39
Cyrus Avatar answered Oct 28 '25 01:10

Cyrus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!