Reputation: 181
I have a large file that consists of tests run sequentially. Each test has a test name and test data. I want filter out all tests that failed into a separate file. - The test names are enclosed in square brackets. - The test data in the example below are the 4 lines in each test - If a test fails it will have the keyword FAILED in it. Here is a simple example:
[CPU]
aaaa
bbbb
cccc
[Drives]
dddd
FAILED eeee
ffff
[Memory]
gggg
hhhh
iiii
[Power]
FAILED jjjj
FAILED kkkk
llll
[Graphics]
mmmm
nnnn
oooo
In this example 2 of the 5 tests failed so the output file would be:
[Drives]
dddd
FAILED eeee
ffff
[Power]
FAILED jjjj
FAILED kkkk
llll
Using BASH I can use grep to find the failed lines but I don't know how I can extract the full tests including the test names. I was thinking that after finding a match with grep I would use a do while loop and output each line to the file until it finds the [] above and below it.
Upvotes: 1
Views: 1939
Reputation: 5092
You can also use sed
command
sed ':a;N;/\[.*\]$/{/.*FAILED.*\n/{P;D};D;t};s/\n/-/g;$d;t a;' file_name | sed 's/-/\n/g'
Explanation:
N -- Get the two line and store in the pattern space .
t a -- continue the loop and append the line to the pattern space
P -- Print the first line in the pattern space .
D -- Delete the first line in the pattern space .
Execution way:
N
get the two line and t loop
append each line into the pattern space until the next block of header. After the header all the lines are considered as a single line by using substitution. Then some validation is performed like if FAILED
pattern is found then print the until newline is found and delete it, else delete the line until newline, then continue the process. Finished all the process then substitute the every field with newline.
Upvotes: 2
Reputation:
The first thing that comes to my mind is very ugly solution with temporary files:
split -l 4 --additional-suffix=.txt yourfile.txt tmpfile; grep -C 4 FAILED tmpfile*.txt
It is definitely not most efficient but could be useful especially if (as you wrote) you want to store failed output in separate files anyway.
Upvotes: 1
Reputation: 75498
Using GNU awk:
gawk -v RS='\\[[^\\]]+\\]' /FAILED/ { printf "%s%s", p, $0 } { p = RT }' file
Output:
[Drives]
dddd
FAILED eeee
ffff
[Power]
FAILED jjjj
FAILED kkkk
llll
Upvotes: 0