Delete the matching line and several more from a file

grepsedtext processing

I have a text file called file_a.txt.
My first command is

grep -A 12 ".production =" file_a.txt

The output is a few block.
Each block of string contains 13 rows

I specifically want to delete all the block of strings I got with the grep command from the original file file_a.txt.
I do not want to send the grep output to a new file.
Also I do not want to to use grep -v because it will not work in my case.

I have tried something like things like this, but nothing is working:

cut < grep -A 12 ".production =" file_a.txt

sed -i '/`grep -A 12 ".production ="`/d' file_a.txt

Best Answer

GNU sed way

In GNU sed (if you are using some Linux distribution it should be default sed implementation), you can use something like this:

sed '/.production =/,+12d' inputfile.txt

How it works:

  1. It scans the input file line by line (this is how sed works) and check if the command should be used.
  2. Our command is d (the last character) which means delete the line.
  3. But this command will only run if current line does match our range.
  4. The range is specified by two arguments (start and end of range, inclusive) delimited by , character. First is a regular expression /.production =/ which match each line containing this expression. Second argument is +12d which means 12 lines from start range.
  5. So our range matches each line that matches expression and next 12 lines and deletes them.
  6. All the other lines are printed to the output (default sed behaviour).

Portable, ugly way

This one should work on other sed implementation but involves much more typing and is not so robust:

sed '/.production =/{N;N;N;N;N;N;N;N;N;N;N;N;d}' somefile.txt

How it works:

  1. It scans the input file line by line (this is how sed works) and check if the command should be used.
  2. It checks if the line matches the /.production =/ pattern. If so, it runs all the commands in {} braces.
  3. We run N comamnd 12 times. N command reads next line and appends it to current buffer. So after we run it 12 times, we have 13 lines concatenated in current buffer (first line + 12 read by N commands).
  4. Now we run d command which deletes this concatenated 13 lines.
  5. sed continues until it finds another pattern and again deletes 13 lines. All the other lines are printed (default sed behaviour).
Related Question