如何正确合并制表符分隔文件

时间:2016-02-27 13:14:59

标签: bash awk merge

如果我有以下两个文件:

00001    missing     affected          0.0132    case
00002    missing     not affected      0.042     control
00003    missing     affected          0.12      case
00004    present                                 case
00005    missing     affected          0.001     control

00001    A     406      R     case
00002    Q     612      B     case
00004    N/A   102            case                    
00005    C                    control

如何通过每个文件的第一列和最后一列连接这两个表,以便得到类似的内容:

00001    missing     affected          0.0132    case    A     406      R
00002    missing     not affected      0.042     
00003    missing     affected          0.12
00004    present                                 case    N/A   102                              
00005    missing     affected          0.001     control       00005    C                    

注意第二个表中的00003丢失,第二个表中的第2行与表1中的case列不一致,因此这实际上是左连接的SQL等价物。

谢谢。

3 个答案:

答案 0 :(得分:2)

首先将输入中的字段分隔符更改为不同于空格的内容(因为空格位于not affected内)。所以我们假设输入是这样的(merge1.csv):

00001;missing;affected;0.0132;case
00002;missing;not affected;0.042;control
00003;missing;affected;0.12;case
00004;present;;;case
00005;missing;affected;0.001;control

和(merge2.csv):

00001;A;406;R;case
00002;Q;612;B;case
00004;N/A;102; ;case
00005;C; ; ;control

现在

  1. 从第1列和第5列创建一个排序键,并使用<merge1.csv awk -v FS=';' -v OFS=';' '{print $1 "-" $5 ";" $0}' | sort -k1,1
  2. 之类的内容对其进行排序
  3. 在这样的连接命令中一起使用上述两个

    join -t';' -j1 -e "" -a 1  -o 1.2,1.3,1.4,2.6,2.3,2.4,2.5 <( <merge1.csv awk -v FS=';' -v OFS=';' '{print $1 "-" $5 ";"  $0}' | sort -k1,1 ) <( <merge2.csv awk -v FS=';' -v OFS=';' '{print $1 "-" $5 ";"  $0}' | sort -k1,1 )
    

    您想阅读选项-a -e-o

  4. 上的'加入'手册页
  5. 除了最后一行中的最后两列外,这或多或少会提供您想要的输出。

答案 1 :(得分:2)

我不确切地知道算法会得到什么输出(例如,为什么00005是最后一行输出中的倒数第二个字段?)并研究an SQL equivalent of a left join手段超出了我的工资水平,但希望这会让你接近:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR { a[$1,$NF] = $0; next }
{
    split(a[$1,$NF],b)
    $NF = b[5] OFS b[2] OFS b[3] OFS b[4]
    print
}

$ awk -f tst.awk file2 file1
00001   missing affected        0.0132  case    A       406     R
00002   missing not affected    0.042
00003   missing affected        0.12
00004   present                 case    N/A     102
00005   missing affected        0.001   control C

只是这样你可以看到标签在上面的位置排列:

$ awk -f tst.awk file2 file1 | column -s$'\t' -t
00001  missing  affected      0.0132  case     A    406  R
00002  missing  not affected  0.042
00003  missing  affected      0.12
00004  present                        case     N/A  102
00005  missing  affected      0.001   control  C

如果您编辑问题以包含您希望实施的任何算法的伪代码,那么我相信有人可以帮助您将其转换为awk。

此外,如果file1中缺少一个键字段但存在于file2中,那么请在样本输入/输出中包含该字符,以便我们可以看到您希望如何处理该字段。

答案 2 :(得分:1)

你可以使用这个awk:

awk 'BEGIN{FS=OFS="\t"} {
   k = $1 FS $NF
} FNR==NR {
   gsub("^" $1 FS "|" FS $NF "$", "")
   a[k] = $0
   next
} {
   $NF = (k in a) ? $NF OFS a[k] : ""
} 1' file2 file1 |
column -s $'\t' -t

column -s $'\t' -t用于以表格格式格式化输出。

00001  missing  affected      0.0132  case     A    406  R
00002  missing  not affected  0.042
00003  missing  affected      0.12
00004  present                        case     N/A  102
00005  missing  affected      0.001   control  C