用awk在不同行打印满足条件的行

Print line that meets conditions in different lines with awk

总新手。 awk 可以打印以下内容:

w171930 t1 Y z2545377 <--- print this line
w171930 t2 X z4495648
w171931 t1 Y z2555698 <--- print this line
w171931 t2 X z5505690
w171932 t1 Y z2554345 <--- print this line
w171932 t2 X z5507345
w171933 t1 Y z2214694
w171933 t2 Y z8022710
w171933 t3 Y z2143462
w171933 t4 Y z6217556
w171933 t5 Y z9608343
w171933 t6 Y z9984446
w171933 t7 Y z2985572
w171933 t8 Y z6334512 <--- print this line
w171933 t9 X z6503375
w171943 t1 Y z2441603 <--- NO print this line
w171943 t2 X z4644534
w171943 t3 Y z2164440
w171944 t1 Y z2165532

搜索 $3 == "X" 如果下一行有 $2 == "t1"

则打印上一行

目标

w171930 t1 Y z2545377
w171931 t1 Y z2555698
w171932 t1 Y z2554345
w171933 t8 Y z6334512

我只打印了前一行,但我不知道如何执行完整的条件

awk ' == "Y" { Y=[=12=]; next; } { if ( =="X") print Y;}'

表达不正确请见谅

awk '=="t1"{ if(prev2!="" && prev!="") print prev2 }
     { prev=(=="X"?prev2:""); prev2=[=10=] }' input
  • =="t1" 仅适用于第二个元素 = "t1" 的行。当 prevprev2 有值时,我们应该打印该值。
  • 当第三个元素等于“X”时,
  • prev 将包含 prev2 的值
  • prev2 将具有需要返回的行的值。

另一个解决方案awk

$ awk '=="t1" && third=="X"{print line2}
       {line2=line1; line1=[=10=]; third=}' ip.txt
w171930 t1 Y z2545377
w171931 t1 Y z2555698
w171932 t1 Y z2554345
w171933 t8 Y z6334512
  • line1 将有前一行,line2 将有前一行但只有一行
  • third保存上一行第3个字段内容
  • 当当前行的第二个字段为t1时,检查上一行的第三个字段是否为X,如果是,则打印前一行

关于您的要求:

Search on  == "X" and print the previous line if the next line has a  == "t1"

就像在生活中一样,在软件中,根据已经发生的事情而不是将要发生的事情来做事要容易得多,所以不要根据下一件事来写需求,而是根据上一件事来写需求事情过去了,你会发现概念化和编写代码来实现它们要容易得多。在这种情况下你的要求应该写成:

If  == "t1" in the current line and  == "X" in the previous line then print the line before that.

这导致明显的实现:

$ awk '(=="t1") && (p3=="X") {print pp0} {pp0=p0; p0=[=12=]; p3=}' file
w171930 t1 Y z2545377 <--- print this line
w171931 t1 Y z2555698 <--- print this line
w171932 t1 Y z2554345 <--- print this line
w171933 t8 Y z6334512 <--- print this line

如果需要,您可以使用 regex 执行此操作,这可以在 Perl 中完成:

perl -0777 -nE 'while (/^.*\R(?=(?:\S+\s){2}X\s\S+\R\S+\st1)/gm) {print $&}' file

或者,对正则表达式稍作修改,您可以使用 GNU Grep:

grep -ozP '.*\R(?=(?:\S+\s){2}X\s\S+\R\S+\st1)' file | tr -d '[=11=]0'

ruby:

ruby -e 'puts $<.read.scan(/(.*\R)(?=(?:\S+\s){2}X\s\S+\R\S+\st1)/)' file

其中任何一个(使用您的示例输入)打印:

w171930 t1 Y z2545377 <--- print this line
w171931 t1 Y z2555698 <--- print this line
w171932 t1 Y z2554345 <--- print this line
w171933 t8 Y z6334512 <--- print this line

有点冗长,但它完成了工作:

<<<"${aa}" mawk '

 BEGIN {
       _+=++_
 } {
     do {____=$((__=$_)<"") 

     } while($(_+getline)=="Y")
   
     if(___<("X"==$++_)) {

       printf("%s%.*s",____,\
           (___=__!="t1")<_,ORS) }; -—_}'

w171930 t1 Y z2545377
w171931 t1 Y z2555698
w171932 t1 Y z2554345
w171933 t8 Y z6334512