首页 文章

读取上一行和下一行的列值,但使用awk将它们作为附加字段插入当前行

提问于
浏览
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_No 的每个后续出现, Crt_Act_No 与上一行的 Act_No 相同, Prs_Act_No 与当前行上的 Act_No 相同, Cd_Act_No 与下一行的 Act_No 相同 . 对于除最后一行之外的所有后续行具有相同的 Apl_No ,这将继续 . 在最后一行中, Crt_Act_NoPrs_Act_No 以与上述行相同的方式填充,但是当遇到第一个唯一的 Apl_No 时,需要从第一行的 Act_No 中拉出 Cd_Act_No .

我希望用awk实现这一目标 . 任何人都可以帮我解决这个问题 .

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
    

相关问题