2

I want the awk to go to the beginning of the block of lines to start processing it again once it hit the bottom of that block and processed its last line.

Basically, if block of text is

<START of block>
Hi 
How 
Are
You
<END of block>

I want awk to check if "You" is last line of the block, then to print that block else not the print it. There are multiple blocks of texts with different values in my file.

If I can make awk to go to a specific line stored in 'line' variable to start processing then my purpose would be solved.

closed as unclear what you're asking by Sparhawk, Mr Shunz, JigglyNaga, muru, αғsнιη Apr 18 at 17:15

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • How does awk know when it's at the last line of the block? By pattern? By line number? By the pattern of the next line? Also, what do you mean by "processing"? Could you provide your expected output? – Sparhawk Apr 16 at 10:36
  • 2
    Are the <START of block> and <END of block> literal strings? if not, how are "blocks" delimited in your file? – steeldriver Apr 16 at 11:11
  • You say you want to "go to the beginning" and "start processing it again". Do you want to loop over the first block forever? – JigglyNaga Apr 18 at 9:28
0

if I understood correctly: - your input has a dedicated line saying "<START of block>", and another for "<END of block>", and you want to print that block (including those 2 markers? or not?) if they end up with "You" at the line before "<END of block>" ?

then:

awk -v regstart="<START of block>" -v regend="<END of block>" -v reglast="You" '
 BEGIN { rem="we will remember a block between those regstart and regend markers, and only print it if the last line matches reglast"
         remember=0; rem="by default we are not inside a block, so we do not remember lines until we match the regstart"
 }

 ( $0 ~ regstart ) {
     remember=1; nb=0; 
 }

 ( remember==1 )   {
     line[++nb]=$0 ; 
 }

 ( $0 ~ regend   ) { 
     remember=0; rem="we reached the end of block, we do not remember anymore the lines we see until next regstart"
     if ( line[(nb-1)] ~ reglast ) {
          ## for(i=2;i<=(nb-1);i++) { rem="this version do NOT show the 2 marker lines"
          for(i=1;i<=nb;i++) { rem="this version shows the 2 marker lines"
              print line[i]
          }
          ## print "" ; rem="uncomment this line if you want a separator lines between blocks"
     }
 }

'

Note1: I use regexps to match start, end and last line, but you could use "==" intead to compare exact strings.

Note2: the printing part: could go from 2 to nb-1 to not show the START (stored in line[1]) and END (stored in line[nb]) lines.

Note3: the script above happily processes every blocks and only prints those that finished with a line matching "reglast". Ie it doesn't only print one, but all matching blocks.

0

A shorter awk alternative for an input at below:

< infile awk -v RS='\n<END of block>' '$NF == "You" { print $0 RS }'
<START of block>
Hi
How
Are
You
<END of block>

<START of block>
thank
You
<END of block>

$NF here (according to the defined RS (Record Separator) setting to a static string that makes we separate each block based on that) indicates the value of last line, so if it's equal with Yes string then print that block and revert back RS as well.

Input file:

<START of block>
Hi
How
Are
You
<END of block>
<START of block>
Hi
How
Are
not YOU
<END of block>
<START of block>
thank
You
<END of block>
<START of block>
welcome
to
Unix
<END of block>

Not the answer you're looking for? Browse other questions tagged or ask your own question.