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} } '