使用 awk 匹配模式并仅打印非零字段

Match a pattern and print only non zero field using awk

我有一个这样的文件,我想搜索模式匹配“/4126/”并仅打印月份和年份以及金额(金额并不总是在 2014 年 1 月,如下例所示)。

awk -F! '/4126/ {print [=10=]}'  prints the entire line

但我只需要打印 month/year 和金额如下:

Jan 2014
25492.00

此处提供了文件中的示例。

    +=====================================================================+
    ! Code  !  Jan 2014 !  Feb 2014 !  Mar 2014!    Arrears!  T o t a l s !
    +=====================================================================+
    ! 1101  !  26290.00 !  26290.00 !  26290.00!      0.00 !  3,15,480.00 !
    ! 1102  !    480.00 !    480.00 !    480.00!      0.00 !     5,760.00 !
    ! 2104  !  24213.09 !  25198.97 !  25198.97!      0.00 !  2,73,205.69 !
    ! 2107  !      0.00 !      0.00 !      0.00!      0.00 !    14,991.20 !
    ! 2113  !    275.00 !    275.00 !    275.00!      0.00 !     3,300.00 !
    ! 4114  !      0.00 !      0.00 !   1106.00!      0.00 !     4,424.00*!
    ! 4123  !   4667.00 !      0.00 !      0.00!      0.00 !     4,667.00 !
    ! 4126  !  25492.00 !      0.00 !      0.00!      0.00 !    25,492.00*!

请提供执行此操作的 awk 公式。提前致谢。

你就快完成了,$0 是整行,你需要一个特定的字段(和 header)

$ awk -F! 'NR==2{h=} ~/\y4126\y/{print h; print }' file

Jan 2014 
25492.00 

您的示例输出打印了之前的值,如果不是拼写错误,您应该保留之前的行并在匹配后打印。

要消除错误匹配,请将模式保留到相应的字段并带有单词边界。

要打印所有非零金额,您可以执行以下操作

$ awk -F! 'NR==2{h[3]=; h[4]=; h[5]=}
   ~/\y2104\y/{for(i=3;i<=5;i++) 
                    if($i!=0) 
                       {header=header OFS h[i]; 
                        line=line OFS $i
                       } 
                print header;
                print line}' file 


   Jan 2014    Feb 2014    Mar 2014
   24213.09    25198.97    25198.97
awk '~/Jan/{print , };~/4667.00/{print }' file
 Jan 2014
 4667.00

由于我没有定义任何字段分隔符,awk 使用其内置 space。因此,如果第 4 列匹配 Jan 打印字段 4 和 5。如果第 4 列匹配 4667 打印字段 4,则再次相同。

非常不清楚您是要打印特定列的值还是名为 "Jan 2014" 的列的值和/或跨所有列和 header 行的值您在其中找到它的列或其他内容,但也许这就是您想要的:

$ awk -F' *! *' -v tgt=4123 -v col=3 'NR==2{hdr=$col} ==tgt{print hdr ORS $col}' file
Jan 2014
4667.00

$ awk -F' *! *' -v tgt=2104 -v col=4 'NR==2{hdr=$col} ==tgt{print hdr ORS $col}' file
Feb 2014
25198.97

鉴于您的新要求:

$ cat tst.awk
BEGIN { FS=" *! *"; OFS="\t" }
NR==2 { split([=11=],hdrs) }
==tgt {
    for (i=3;i<(NF-1);i++) {
        if ($i != 0) {
            hdr = (hdr ? hdr OFS : "") hdrs[i]
            txt = (txt ? txt OFS : "") $i
        }
    }
}
txt { print hdr ORS txt }

$ awk -v tgt=4126 -f tst.awk file
Jan 2014
25492.00

$ awk -v tgt=2104 -f tst.awk file
Jan 2014        Feb 2014        Mar 2014
24213.09        25198.97        25198.97

以上内容适用于任何 awk,并且仅在找到目标值时才产生输出(即,如果未找到目标值,则不会打印空行或其他任何内容)。

实际上 - 在阅读了您在@karakfa 的回答下的评论后,这可能就是您想要的:

$ cat tst.awk
BEGIN { FS=" *! *"; OFS="\t" }
NR==2 { split([=12=],hdrs) }
==tgt {
    for (i=3;i<(NF-1);i++) {
        if ($i!=0) {
            print hdrs[i] ORS $i
        }
    }
}

$ awk -v tgt=2104 -f tst.awk file
Jan 2014
24213.09
Feb 2014
25198.97
Mar 2014
25198.97

如果您提供了一个从多列生成输出的示例,您就可以避免我们猜测。