1

This question already has an answer here:

I've been reading How to grep -v and also exclude the next line after the match? and wondering how to exclude the 2 lines, or any number after the match using sed or any other practical tools.

user@linux:~$ cat -n file.txt 
     1  SomeTestAAAA
     2  Random String
     3  EndTest
     4  SomeTestABCD
     5  Random String
     6  EndTest
     7  SomeTestDEFG
     8  Random String
     9  EndTest
    10  SomeTestAABC
    11  Random String
    12  EndTest
    13  SomeTestACDF
    14  Random String
    15  EndTest
user@linux:~$ 

1st Question

I was able to accomplish this using grep -P as follows; unfortunately there is unwanted -- character in the output.

How to remove this?

user@linux:~$ grep -P -A 2 'SomeTest(?!AA)' file.txt
SomeTestABCD
Random String
EndTest
SomeTestDEFG
Random String
EndTest
--
SomeTestACDF
Random String
EndTest
user@linux:~$ 

Question 2

I've also managed to do this with awk as shown in previous answer. However this is only working on this case because of the similar EndTest pattern. What if EndTest is some random word and doesn't have pattern.

Could we do something similar as grep -v -A 2 SomeTestAA? I know this won't work, but the desired output would be similar as follows.

user@linux:~$ awk  'BEGIN{ RS=ORS="\nEndTest\n"} !/'"^SomeTestAA/" file.txt 
SomeTestABCD
Random String
EndTest
SomeTestDEFG
Random String
EndTest
SomeTestACDF
Random String
EndTest
user@linux:~$ 

marked as duplicate by don_crissti, user88036, RalfFriedl, G-Man, jimmij Oct 2 '18 at 8:54

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • For Q1, see if your grep supports a --no-group-separator option – steeldriver Oct 1 '18 at 7:56
1

Using GNU sed:

$ sed '/AA/,+2d' <file
SomeTestABCD
String
EndTest
SomeTestDEFG
String
EndTest
SomeTestACDF
String
EndTest

The GNU sed script finds lines containing the string AA and then deletes that line and the following two lines from the input. The +2 relative addressing is a GNU sed extension to standard sed.

Using standard sed, deleting two lines:

sed -n '/AA/{n;n;d;}; p' <file

This uses sed without implicitly outputting every line of input (with -n). When the AA pattern is matched, the next two lines are explicitly read and deleted. All lines that don't trigger the pattern will be printed.

With standard sed, deleting to the EndTest line:

sed '/AA/,/^EndTest$/d' <file

This deletes all lines from the lines that contains the string AA to the immediately following line that matches the pattern ^EndTest$.


Using awk to ignore two lines after matching AA:

awk '/AA/ { getline; getline; next } 1' <file

Using awk in the same way as the last sed variation:

awk '/AA/,/^EndTest$/ { next } 1' <file
  • 1
    with sed : sed '/AA/!b;N;N;d' or with awk : awk '/AA/{f=3}f{f--;next}1' – ctac_ Oct 1 '18 at 7:55
  • Note that these only work with OP's sample. As soon as those /PATTERN/,+N ranges overlap these solutions will be off - the only one that works with arbitrary input in this case is the awk one-liner suggested by @ctac_ A simple range address is not enough to do this properly (so as to handle arbitrary input) with sed. Depending on the value of N it can get rather complicated... – don_crissti Oct 1 '18 at 10:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.