2016-02-25 42 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,多維數組和排序數組遍歷。