0

我希望你能帮我解决我的问题。

我有一个包含 3 列数据的输入文件,如下所示:

Apl_No Act_No Sfx_No 
100    10     0
100    11     1
100    12     2
100    13     3
101    20     0
101    21     1

我需要创建一个输出文件,其中包含输入中的数据和输出中的 3 个附加文件。它应该如下所示:

Apl_No Act_No Sfx_No Crt_Act_No Prs_Act_No Cd_Act_No
100    10     0       -         -          -
100    11     1       10        11         12
100    12     2       11        12         13
100    13     3       12        13         10
101    20     0       -         -          -
101    21     1       20        21         20

每个Apl_No都有一组Act_No映射到它。需要创建 3 个新字段:Crt_Act_No Prs_Act_No Cd_Act_No. 当Apl_No遇到第一个唯一值时,列值 4、5 和 6 ( Crt_Act_No Prs_Act_No Cd_Act_No) 需要被划掉。对于随后出现的每一个相同Apl_NoCrt_Act_No,the 与Act_No上一行中的Prs_Act_No相同,Act_No与当前行中的Cd_Act_No相同,并且Act_No与下一行中的相同。Apl_No对于除最后一行之外的所有后续行,这将继续。在最后一行中Crt_Act_NoPrs_Act_No以与上述行相同的方式填充,但是当遇到第一个唯一时,Cd_Act_No需要Act_No从第一行中拉出Apl_No

我希望使用 awk 来实现这一点。谁能帮我解决这个问题。

4

1 回答 1

2

一种解决方案:

awk '
    ## Print header in first line.
    FNR == 1 {
        printf "%s %s %s %s\n", $0, "Crt_Act_No", "Prs_Act_No", "Cd_Act_No";
        next;
    }

    ## If first field not found in the hash means that it is first unique "Apl_No", so
    ## print line with dashes and save some data for use it later.
    ## "line" variable has the content of the previous iteration. Print it if it is set.
    ! apl[ $1 ] {
        if ( line ) {
            sub( /-/, orig_act, line );
            print line;
            line = "";
        }
        printf "%s %s %s %s\n", $0, "-", "-", "-";
        orig_act = prev_act = $2;
        apl[ $1 ] = 1;
        next;
    }

    ## For all non-unique "Apl_No"... 
    {
        ## If it is the first one after the line with
        ## dashes (line not set) save it is content in "line" and the variable
        ## that I will have to check later ("Act_No"). Note that I leave a dash in last
        ## field to substitute in the following iteration.
        if ( ! line ) {
            line = sprintf( "%s %s %s %s", $0, prev_act, $2, "-" );
            prev_act = $2;
            next;
        }

        ## Now I know the field, so substitute the dash with it, print and repeat
        ## the process with current line.
        sub( /-/, $2, line );
        print line;
        line = sprintf( "%s %s %s %s", $0, prev_act, $2, "-" );
        prev_act = $2;
    }
    END {
        if ( line ) {
            sub( /-/, orig_act, line );
            print line;
        }        
    }
' infile | column -t

这会产生:

Apl_No  Act_No  Sfx_No  Crt_Act_No  Prs_Act_No  Cd_Act_No
100     10      0       -           -           -
100     11      1       10          11          12
100     12      2       11          12          13
100     13      3       12          13          10
101     20      0       -           -           -
101     21      1       20          21          20
于 2012-10-04T20:59:18.150 回答