How to filter out 2 lines for each line matching the grep regex?
this is my minimal test:
SomeTestAAAA EndTest SomeTestABCD EndTest SomeTestDEFG EndTest SomeTestAABC EndTest SomeTestACDF EndTest
And obviously I tried e.g. grep -vA 1 SomeTestAA which doesn’t work.
desired output is:
SomeTestABCD EndTest SomeTestDEFG EndTest SomeTestACDF EndTest
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You can use grep with -P (PCRE) :
grep -P -A 1 'SomeTest(?!AA)' file.txt
(?!AA) is the zero width negative lookahead pattern ensuring that there is no AA after SomeTest.
Test :
$ grep -P -A 1 'SomeTest(?!AA)' file.txt SomeTestABCD EndTest SomeTestDEFG EndTest SomeTestACDF EndTest
Method 2
You can use GNU sed‘s d command to delete a line, and prefix it with /pat/,+N to select lines matching the pattern and the subsequent N lines. In your case, N = 1 since you only want to delete the single subsequent line after a matching line:
sed -e '/SomeTestAAAA/,+1d'
Method 3
Here’s a sed solution (with -n i.e. no auto-printing) that works with arbitrary input:
sed -n '/SomeTestAA/!p # if line doesn't match, print it
: m # label m
//{ # if line matches
$!{ # and if it's not the last line
n # empty pattern space and read in the next line
b m # branch to label m (so n is repeated until a
} # line that's read in no longer matches) but
} # nothing is printed
' infile
so with an input like
SomeTestAAXX SomeTestAAYY + one line SomeTestONE Message body EndTest ######## SomeTestTWO something here EndTest SomeTestAABC + another line SomeTestTHREE EndTest SomeTestAA + yet another line
running
sed -n -e '/SomeTestAA/!p;: m' -e '//{' -e '$!{' -e 'n;b m' -e '}' -e'}' infile
outputs
SomeTestONE Message body EndTest ######## SomeTestTWO something here EndTest SomeTestTHREE EndTest
that is, it removes exactly the lines that grep -A1 SomeTestAA infile would select:
SomeTestAAXX SomeTestAAYY + one line -- SomeTestAABC + another line -- SomeTestAA + yet another line
Method 4
Tried with below GNU sed command and it worked fine
command
sed '/SomeTestAA/,+1d' filename
output
SomeTestABCD EndTest SomeTestDEFG EndTest SomeTestACDF EndTest
Method 5
One option is to use perl compatible regular expression grep:
pcregrep -Mv 'SomeTestAA.*n' file
The option -M allows pattern to match more then one line.
Method 6
Using standard sed:
$ sed '/SomeTestAA/{ N; d; }' file
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest
The sed script parses the input file line by line, and when a line matches the pattern SomeTestAA, the two sed editing commands N and d are executed. The N command appends the next line of input to the pattern space (the buffer that sed can edit), and the d deletes the pattern space and starts the next cycle.
Method 7
You might have better luck with something that looks at multi-line regions as single records. There’s an sgrep which I haven’t used much.
There’s also awk, where you can set the input record separator, and output record separator, to whatever you like.
pat="^SomeTestAA"
awk 'BEGIN{ RS=ORS="nEndTestn"} !/'"$pat/" foo
Most of the awk program is single-quoted, but I change to double quotes at the end so the $pat shell variable can be expanded.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0