Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search for a String, and retrieve all lines following it until another specific pattern

From a unix script, I want to search a text file for a string and then return all the lines following the pattern up until a line that contains the word "Failed".

For example,

Test Case Name "Blah"
Error 1
Error 2
Error 3
Failed
Test Case Name "Foo"
Pass
Test Case Name "Red"
Pass

In the above, I want to search for "Blah", and then return:

Error 1
Error 2
Error 3

Up until the line "Failed". There can be any number of "Error" lines between "Blah" and "Failed".

Any solutions using sed, awk, etc. are acceptable.

Thanks!

like image 718
Konsole Avatar asked Dec 15 '25 12:12

Konsole


2 Answers

Here is the awk version:

$ awk '/Failed/{p=0}p;/Blah/{p=1}' file
Error 1
Error 2
Error 3

And if you don't mind printing the boundary lines, you can do

awk '/Blah/,/Failed/' file

Some explanations how this works: an awk script is essentially a series of blocks with the structure filter{actions}, where the filter defines for which input records, the actions will be applied.

So the first block /Failed/{p=0} says that if we find a record that contains the regular expression Failed, we set the variable p to zero.

The second block p; uses the default action, which is to print the current record. So for each record that is read, the script checks the value of the p variable, and prints the record if p has a non-zero value (which is equivalent to the true condition).

The third block /Blah/{p=1} says that if we find a record that contains the regular expression Blah, to set the variable p to one.

So if we put them all together, the script starts reading all input lines without printing them (since the initial value of p is zero). After a record containing Blah is found, the following records are printed until a record containing Failed is found. Since the blocks are examined for each record in the order that they appear, the order of the three blocks will determine what happens to the boundary records. For example, if the boundary lines were to be printed we could write the script as awk '/Blah/{p=1}p;/Failed/{p=0}' file.

The second command awk '/Blah/,/Failed/' file uses a range construct (the comma). The operation of the range construct is documented nicely here: https://www.gnu.org/software/gawk/manual/html_node/Ranges.html

like image 67
user000001 Avatar answered Dec 18 '25 08:12

user000001


This might work for you:

sed -n '/Blah/,/Failed/{//!p}' file
like image 21
potong Avatar answered Dec 18 '25 08:12

potong



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!