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

Bash 如何正确合并制表符分隔的文件,bash,awk,merge,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

如果我有以下两个文件:

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    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等价物


谢谢。

首先将输入中的字段分隔符更改为与空格不同的分隔符(因为空格在
中,不受影响
)。因此,假设输入如下(merge1.csv):

和(merge2.csv):

现在


  • 从第1列和第5列中创建一个排序键,并在其上使用类似于
    的内容进行排序。首先将输入中的字段分隔符更改为与空格不同的内容(因为空格位于
    不受影响的
    中)。因此,假设输入如下(merge1.csv):

    和(merge2.csv):

    现在


  • 从第1列和第5列中创建一个排序键,并使用类似于
    的内容对其进行排序。我不清楚获得该输出的算法是什么(例如,为什么
    00005
    是输出最后一行中的第二个字段?)研究一下左连接的SQL等价物的意思比我的薪水高,但希望这能让你接近:

    $ 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


    此外,如果文件1中可能缺少一个键字段,但该字段出现在文件2中,那么请将该情况包含在示例输入/输出中,以便我们可以看到您希望如何处理该问题。

    我不太清楚获得该输出的算法是什么(例如,
    00005
    为什么是输出最后一行的第二个字段?)研究一下左连接的SQL等价物的意思比我的薪水高,但希望这能让你接近:

    $ 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

    此外,如果文件1中可能缺少一个键字段,但该字段出现在文件2中,那么请将该情况包含在示例输入/输出中,以便我们可以看到您希望如何处理该问题。

    您可以使用此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
    
    您可以使用此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
    


    请显示您的编码工作。您可以先为每个文件创建一个“人工”前导字段,以便简单地
    join
    ing结果:
    awk'{print$1$NF,$0}'
    请显示您的编码工作。您可以先创建一个“人工”前导字段prep for simply
    join
    ing结果中每个文件的前导字段:
    awk'{print$1$NF,$0}'
    没有理由更改字段分隔符-选项卡与分号一样合理且易于处理。只需使用
    BEGIN{FS=OFS=“\t”}
    @EdMorton复制/粘贴提供的示例,结果是空格,而不是制表符。因此,获得一个不同于空格的分隔符的步骤。
    还有一个额外的好处,那就是我们可以看到正在发生的事情,尤其是当某些列中存在缺失/空值时。啊,你的意思是他应该更改它,以便为这个问题提供示例输入/输出,而不是他应该在实际应用程序中更改它。好的,很公平。没有理由改变字段分隔符-制表符和分号一样合理和容易处理。只需使用
    BEGIN{FS=OFS=“\t”}
    @EdMorton复制/粘贴提供的示例,结果是空格,而不是制表符。因此,获得一个不同于空格的分隔符的步骤。
    还有一个额外的好处,那就是我们可以看到正在发生的事情,尤其是当某些列中存在缺失/空值时。啊,你的意思是他应该更改它,以便为这个问题提供示例输入/输出,而不是他应该在实际应用程序中更改它。好的,很公平。FWIW您可以替换
    s=$0;sub($1 FS,”,s);分包(FS$NF,”,s);a[k]=s
    gsub(“^”1fs | FS$NF“$”,”);a[k]=$0
    甚至
    gsub(/^[^\t]+\t |\t+[^\t]+/,”);a[k]=$0}
    如果$1和$NF中可能有RE元字符。更重要的是-
    SEP
    是未定义的,因此您将这两个字段串联起来,这通常是“一件坏事”(
    ab c
    a bc
    ->
    abc
    )。您可以使用SUBSEP或FS来代替SEP。不客气,您确实应该做些事情来解决SEP未定义的问题-或者使用已定义的内容,或者如果您确实想将它们连接起来(不推荐),那么就去掉SEP,因为它会误导您。实际上,这里并不真正需要
    SEP
    ,甚至
    FS
    也可以用作两个连接键之间的分隔符。@anubhava是的,我在第一条评论中说可以用subsp或FS来代替。@brucezepplin:很高兴它能起作用。我对它进行了轻微的更新,以在output.FWIW中生成更好的格式,您可以替换
    s=$0;sub($1 FS,”,s);分包(FS$NF,”,s);a[k]=s
    gsub(“^”1fs | FS$NF“$”,”);a[k]=$0
    甚至
    gsub(/^[^\t]+\t |\t+[^\t]+/,”);a[k]=$0}
    如果$1和$NF中可能有RE元字符。更重要的是-
    SEP
    是未定义的,因此您将这两个字段串联起来,这通常是“一件坏事”(
    ab c
    a bc
    ->
    abc
    )。您可以使用SUBSEP或FS代替SEP。不客气,您确实应该对SEP未定义的问题采取一些措施-或者使用已定义的内容,或者如果您真的想将它们连接起来(不推荐),那么就去掉SEP,因为它会误导您。实际上
    SEP