填写空白字段-awk

时间:2018-07-11 15:27:22

标签: bash awk multiple-columns

我有三个文件

A.txt
DRR033612   184474
DRR033613   232882
DRR033614   66017
DRR033615   189965
DRR033616   118663
DRR029180   8439

B.txt
DRR033615   1
DRR033616   3

C.txt
DRR033615   5
DRR029180   10
DRR033612   20
我要使用以下awk命令进行总结的

cat *.txt | awk 'BEGIN{FS=OFS="\t"}{unique[$1]=(unique[$1] FS $2); next}END{for (i in unique) print i,unique[i]}'

我基本上是根据第一列加入文件。 A.txt包含所有项目。

不幸的是,该命令无法按照我想要的方式工作,即,20行的值DRR033612 20没有写在正确的字段中。

这是我的输出:

DRR033614       66017
DRR029180       8439    10
DRR033615       189965  1   5
DRR033616       118663  3
DRR033612       184474  20
DRR033613       232882

这是我想要的输出:

DRR033614       66017
DRR029180       8439        10
DRR033615       189965  1   5
DRR033616       118663  3
DRR033612       184474      20
DRR033613       232882

此外,我希望所有空单元格都被0替换。

4 个答案:

答案 0 :(得分:2)

对于真正的多维数组和ARGIND,使用GNU awk:

$ cat tst.awk
{ vals[$1][ARGIND] = $2 }
END {
    for (key in vals) {
        printf "%s", key
        for (fileNr=1; fileNr<=ARGIND; fileNr++) {
            printf "\t%d", vals[key][fileNr]
        }
        print ""
    }
}

$ awk -f tst.awk A.txt B.txt C.txt
DRR033614       66017   0       0
DRR029180       8439    0       10
DRR033615       189965  1       5
DRR033616       118663  3       0
DRR033612       184474  0       20
DRR033613       232882  0       0

答案 1 :(得分:2)

在辅助函数中带有join

$ function j() { join -a1 -e0 -o1.1,1.2,"$3"2.2 <(sort $1) <(sort $2); } 

$ j <(j file1 file2) file3 1.3, | column -t

DRR029180  8439    0  10
DRR033612  184474  0  20
DRR033613  232882  0  0
DRR033614  66017   0  0
DRR033615  189965  1  5
DRR033616  118663  3  0

这是通过密钥排序的,您可以恢复第一个文件的原始顺序,但是在您的预期输出中似乎不是这样。

答案 2 :(得分:1)

也许明天我会花时间写一个适当的解释,但这应该可以解决问题:

awk 'BEGIN { FS = OFS = "\t" }\
  { if (ARGIND != previousArg) { 
      previousArg = ARGIND;
      for (i in unique) { unique[i] = (unique[i] FS) }} 
    unique[$1]=(unique[$1] $2); next
  }
END {
  for (i in unique) print i,gensub(/\t\t/, "\t0\t", "g", unique[i])
}' *.txt

答案 3 :(得分:0)

GNU awk 解决方案:

awk -v OFS='\t' \
'{ all[FILENAME][$1] = $2 }
 END{
     for (i in all["A.txt"]) {
         r = i OFS all["A.txt"][i];
         r = r OFS int(all["B.txt"][i]) OFS int(all["C.txt"][i]);
         print r
     }
 }' A.txt B.txt C.txt

输出:

DRR033614   66017   0   0
DRR029180   8439    0   10
DRR033615   189965  1   5
DRR033616   118663  3   0
DRR033612   184474  0   20
DRR033613   232882  0   0