Home > database >  Grep between the first (or the Nth) occurence of the first condition and the next occurence of anoth
Grep between the first (or the Nth) occurence of the first condition and the next occurence of anoth

Time:12-28

I have a text like this:

line1
line2
Condition1
line xxx
line xxx
Condition2
line yyy
line yyy
Condition1

How do I can force grep to output:

Condition1
line xxx
line xxx
Condition2

?

CodePudding user response:

With GNU grep you can ask to treat newlines like normal characters with -z and only print matched data with -o. The dot after Condition2 is for a newline at the end. Actually grep shouldn't be used for logic spending more than 1 line and this only works with your sample data

# Bad solution
grep -oz 'Condition1.*Condition2.' textfile

Another tool that should be used for line-oriented actions only is sed, which happens to have the possibilities to work with ranges.

# Not flexible, how to handle additional requirements 
sed -p '/Condition1/,/Condition2/ p' textfile

Better tool is using awk.

# sed-like construction: works for the given requirements
awk '/Condition1/,/Condition2/' textfile
# More flexiple, use p as a boolean for printing
awk '/Condition1/ {p=1} p {print} /Condition2/ {p=0}' textfile

The last command can be changed when you want to add or change requirements (like only pront when closing tag is found too).

CodePudding user response:

Assuming you want to get the block of text between the first Condition1 and the Condition2 closest to it and not print anything if either of them are missing:

$ awk '/Condition1/{f=1} f{rec=rec $0 ORS; if (/Condition2/) {printf "%s", rec; rec=f=""} }' file
Condition1
line xxx
line xxx
Condition2

but if you want to get the text from the Condition1 closest to each Condition2 then:

$ awk '/Condition1/{f=1; rec=""} f{rec=rec $0 ORS; if (/Condition2/) {printf "%s", rec; f=0} }' file
Condition1
line xxx
line xxx
Condition2

There are a few other possibilities depending on your so far unstated requirements.

CodePudding user response:

I am not sure what you need to do with the result, so this is for sure not the best way to do it, but I think it's easier to modify depending on your goal

$ cat testFile | awk '{ if ($0 ~ /Condition1/) { output=$0; next; } if(output == "") next; output=output"\n"$0; if($0 ~ /Condition2/) { print output; output=""; next} } '
  • Related