转到 awk 中的特定行开始处理

转到 awk 中的特定行开始处理

我希望 awk 转到行块的开头,以便在到达该块的底部并处理其最后一行后再次开始处理它。

基本上,如果文本块是

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

我想要 awk 检查“You”是否是该块的最后一行,然后打印该块,否则不打印它。我的文件中有多个具有不同值的文本块。

如果我可以让 awk 转到存储在“line”变量中的特定行来开始处理,那么我的目的就得到了解决。

答案1

如果我理解正确:-您的输入有一个专用行表示“ <START of block>”,另一个表示“ <END of block>”,并且您想要打印该块(包括这两个标记?或不?)如果它们在之前的行中以“You”结尾” <END of block>“?

然后:

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

'

注意1:我使用正则表达式来匹配开始、结束和最后一行,但您可以使用“==”来比较确切的字符串。

注2:打印部分:可以从2到nb-1,以不显示START(存储在行[1]中)和END(存储在行[nb]中)行。

注意3:上面的脚本愉快地处理每个块,并且只打印那些以匹配“reglast”的行结束的块。即它不仅打印一个,而且打印所有匹配的块。

答案2

awk下面是一个较短的输入替代方案:

< 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这里(根据RS静态字符串的定义(记录分隔符)设置,使我们基于此分隔每个块)指示最后一行的值,因此如果它与Yes字符串相等,则打印该块并也恢复回 RS。

输入文件:

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

相关内容