GAWK - 多个BEGIN和END部分

时间:2015-08-21 02:35:40

标签: regex awk gawk

我正在尝试处理一堆使用gawk提取数据的文件。

文件区域固定宽度空格式文件

我正在尝试从两个不同的正则表达式匹配的两个不同行中提取数据,但是在ONE print语句中返回这两行中的数据。

我可以使用.awk文件中的以下内容实现此目的,并使用gawk -f来运行它。第一个BEGIN部分设置输入文件格式(FIELDWIDTHs)和第二个BEGIN我试图使用每个文件循环根据提取的数据输出。第一个END完成内部BEGIN,第二个END匹配外部BEGIN。

但是我一次只能将它应用到一个文件中,因为如果我应用于一堆文件(如gawk -f regex.awk km*.txt中那样,我只得到最后一个文件的输出。

我是否可以为每个文件输入获得一行输出,而不必每次都使用循环输入文件并运行awk脚本的脚本文件。

由于

    BEGIN{
    OFS=","; FIELDWIDTHS ="2 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12";
                printf("Date,  Turnover, SalesA, SalesB, SalesC, SalesD, Other Data\n");
                }

    BEGIN{      Sales = 0;
                SalesA = 0;
                SalesB = 0;
                SalesC = 0;
                SalesD = 0;
                JointSales = 0;
                Turnover = 0;
                OtherData = 0;}

    /^03/ || /^06/ {

          if ($1 == "03") {
            Sales = $15/100;
            SalesA = $17/100;
            SalesB = $26/100;
            SalesC = $20/100;
            SalesD = $22/100;
            JointSales = SalesA - SalesB;
            Turnover = JointSales + SalesB + SalesC + SalesD; }
          else if ( $1 == "06") {
            OtherData = substr($0,183,12)/100; }

    #     printf("%s, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f\n",  getDate(FILENAME), Sales, JointSales, SalesB, SalesC, SalesD, OtherData ) 
    }

    END{printf("%s, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f, %10.2f\n",  getDate(FILENAME), Sales, JointSales, SalesB, SalesC, SalesD, OtherData ) }

    END {}


    function getDate(str)
    {   date = substr(str,3,6);
        year = substr(date,1,2);
        month= substr(date,3,2);
        day=substr(date,5,2);
        odate=(day"/"month"/"year);
       return odate
    }

2 个答案:

答案 0 :(得分:3)

如果您使用的是gawk,那么您很幸运。除了BEGINEND块之外,gawk实现了BEGINFILEENDFILE块,它们可以按照您的需要执行:处理每个文件之前和之后。请参阅handy gawk programming guide

与所有awk实现一样,Gnu awk允许您拥有多个BEGINEND块。在读取第一个文件之前,所有BEGIN块按顺序(从头到尾)运行,并且所有END块在最后一个文件完成后以相同的倒数第一顺序运行。由于两种类型的特殊块使用相同的顺序,因此它们不会“嵌套”。

答案 1 :(得分:0)

awk每次运行只允许一个beginend动作集(尽管它们可以分布在多个块中,它们全部合并为一个动作集)和运行包括您处理的所有文件。

如果你想在每个文件之间做一些,可以使用ARGIND变量来保存当前参数的索引(从零开始)。您只需要维护最后一个参数索引(最初为零),如果实际参数索引不同,则执行您的特殊操作并更新最后一个索引。

对于空文件(没有运行代码),当前参数索引可能比最后一个多一个,因此您可能需要循环,递增最后一个索引,直到达到现在的。

例如,让我们打印每个文件的行,但是在之前,之内和之后都有特殊标记。使用文件a.in

xyzzy
plugh

和一个不包含任何内容的b.in文件,您可以使用以下脚本demo.awk

function middleCheck() {
    while (lastArgInd != ARGIND) {
        print "MIDDLE after "lastArgInd":"ARGV[lastArgInd]
        lastArgInd++
    }
}

BEGIN { print "BEGIN"
        lastArgInd = 1
}

{       middleCheck()
        print "   "$0
}

END {   middleCheck()
        print "END"
}

每个文件之间实现操作:

pax> vi demo.awk ; awk -f demo.awk b.in a.in a.in b.in a.in b.in b.in
BEGIN
MIDDLE after 1:b.in
   xyzzy
   plugh
MIDDLE after 2:a.in
   xyzzy
   plugh
MIDDLE after 3:a.in
MIDDLE after 4:b.in
   xyzzy
   plugh
MIDDLE after 5:a.in
MIDDLE after 6:b.in
END

你必须让你的行动符合你的需要,你现在的内心和内心的#34; end紧随你当前的内心" begin