awk在匹配之上打印3行直到第二场比赛

时间:2014-11-06 05:03:23

标签: unix awk

我有很长的行列表,我想有选择地打印START + 3行,直到END包括。问题是START和END之间的长度是可变的,但我总是希望上面的三行开始 我试过awk:

awk '/START/,/END/' file.txt

但是我无法找到如何在START之上加入三行的方法。 真的很感激任何提示 谢谢!

输入

EFA  
DAD  
ABC  
DEF  
GEF  
START  
EDG  
EFG  
GAD  
END  
CDA  

结果

ABC  
DEF  
GEF  
START  
EDG  
EFG  
GAD  
END  

7 个答案:

答案 0 :(得分:1)

awk '/START/ { if (a) print a; if (b) print b; if (c) print c; }\
     { a=b; b=c; c=$0; }\
     /START/,/END/' file.txt

<强>解释

当遇到匹配/START/{if(a)print a;if(b)print b;if(c)print c}的行时,

/START/打印缓冲区记录,跳过任何空的。

{a=b;b=c;c=$0}移位缓冲区记录,如果需要更多记录,则可以使用数组。

/START/,/END/打印/START//END/

之间的所有记录

答案 1 :(得分:1)

#!awk -f
{
  foo[NR] = $0
}
/START/ {
  bar = NR - 3
}
/END/ {
  while (bar++ <= NR)
    print foo[bar]
}

答案 2 :(得分:1)

awk '/START/{print x3"\n"x2"\n"x;p=1}
     /END/{print;p=0}
     {x3=x2}
     {x2=x}
     {x=$0}p' your_file

测试:

> cat temp
EFA  
DAD  
ABC  
DEF  
GEF  
START  
EDG  
EFG  
GAD  
END  
CDA  
> awk '/START/{print x3"\n"x2"\n"x;p=1}/END/{print;p=0}{x3=x2}{x2=x}{x=$0}p' temp
ABC  
DEF  
GEF  
START  
EDG  
EFG  
GAD  
END  
> 

答案 3 :(得分:1)

同一主题的类似但可能更容易理解的变体:

awk '/START/{for(i=1;i<4;++i)if(NR-i in a)print a[NR-i]}{a[NR]=$0;delete a[NR-3]}/START/,/END/' inputfile

在中间它只存储最后三行,如果有第四行则会丢弃。如果找到字符串START,则会打印前三行(仅当它们存在时)以及STARTEND之间的任何行。

如果STARTEND应该是准确的,那么模式应该是/^START$//^END$/或者代替模式匹配,应该像{{{{{{ 1}}在所有情况下。

输入文件:

$0=="START"

输出:

GEF  
START  
EDG  
EFG  
GAD  
END  
CDA
EFA  
DAD  
ABC  
DEF  
GEF  
START  
EDG  
EFG  
GAD  
END  
CDA  

答案 4 :(得分:1)

可能解释您的要求的一种可能的解决方案:

$ awk '{a[NR]=$0} /START/{s=NR} /END/{for (i=(s-3);i<=NR;i++) print a[i]}' file
ABC
DEF
GEF
START
EDG
EFG
GAD
END

如果有一个或多个START / END块并且你不想让第一个START结束END,那么它将起作用。

答案 5 :(得分:0)

如果START和END只出现一次,您可以使用grep这样的上下文:

grep -B 3 -A 99999 START file | grep -B 99999 END

即。 3行before START和最多99999行,然后在END之前最多99999行。

答案 6 :(得分:0)

使用tac

如果文件中有多个END / STARTS

,则应该有效
tac file | awk '/END/{x=4}y&&x{x--}/START/{y=x}x' | tac