2016-02-25 45 views
0

我试图找出如何根据在bash的第一列合并CSV表行的第一列合并CSV表行,例如:根据在bash

date,added,deleted 
2016-01-20,16,10 
2016-02-08,1,1 

date,added,deleted 
2016-01-11,91,9 
2016-01-15,5,82 
2016-01-20,6,85 

,以便我收到一个包含5列(日期,添加1,删除1,添加2,删除2)的表格,如果不存在匹配,则合并代表相同日期的行并将零置为零:

date,added1,deleted1,added2,deleted2 
2016-01-11,0,0,91,9 
2016-01-15,0,0,5,82 
2016-01-20,16,10,6,85 
2016-02-08,1,1,0,0 

回答

2

awk来救援!

$ awk -F, -v OFS=, 'NR==FNR{h=(NR==1?"1":"");a[$1]=$2 h FS $3 h;next} 
     $1 in a{h=(FNR==1?"2":"");print $1,a[$1],$2 h,$3 h;delete a[$1];next} 
       {print $1,0,0,$2,$3} 
      END{for(k in a) print k,a[k],0,0}' file1 file2 

date,added1,deleted1,added2,deleted2 
2016-01-11,0,0,91,9 
2016-01-15,0,0,5,82 
2016-01-20,16,10,6,85 
2016-02-08,1,1,0,0 

更新:头固定。

请注意,这不是一个有序合并,输出顺序遵循file2记录顺序,file1中的任何记录只能以不同的顺序打印。如果记录的自然顺序将输出输出到sort

+0

散列只影响第一个文件中的不匹配记录(匹配后的剩余部分)并将打印在底部,在这种情况下只有一个。 – karakfa

1

这将合并任意数量的文件与任何数目的字段(假设每个文件具有相同数目的字段),而不仅仅是2个文件,每3个字段:

$ cat tst.awk     
BEGIN { FS=OFS="," } 
NR==1 { hdrKey = $1 } 
{ 
    for (i=1;i<=NF;i++) { 
     vals[$1][ARGIND][i] = $i (FNR>1?"":ARGIND) 
    } 
} 
END { 
    prtRow(hdrKey) 

    PROCINFO["sorted_in"] = "@ind_str_asc" 
    for (date in vals) { 
     prtRow(date) 
    } 
} 
function prtRow(key, val,fileNr,fieldNr) { 
    printf "%s", key 
    for (fileNr=1;fileNr<=ARGIND;fileNr++) { 
     for (fieldNr=2;fieldNr<=NF;fieldNr++) { 
      val = vals[key][fileNr][fieldNr] 
      printf "%s%s", OFS, (val?val:0) 
     } 
    } 
    print "" 
    delete vals[key] 
} 

$ gawk -f tst.awk file1 file2 
date,added1,deleted1,added2,deleted2 
2016-01-11,0,0,91,9 
2016-01-15,0,0,5,82 
2016-01-20,16,10,6,85 
2016-02-08,1,1,0,0 

它使用了GNU AWK 4。 *用于ARGIND,多维数组和排序数组遍历。