Bash 要匹配,请在修改列输入并向输出文件添加额外列的同时合并两个文件

Bash 要匹配,请在修改列输入并向输出文件添加额外列的同时合并两个文件,bash,unix,awk,merge,Bash,Unix,Awk,Merge,我想合并2个文件并将其分配给一个新文件,同时在unix中使用awk添加一个新的不存在的列: 文件1:VDR.txt没有标题,以空格分隔,如下所示: chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1 chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1 chr12-45000000-50000

我想合并2个文件并将其分配给一个新文件,同时在unix中使用awk添加一个新的不存在的列:

文件1:VDR.txt没有标题,以空格分隔,如下所示:

chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1
chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1
chr12-45000000-50000000 --- rs187216594 48225500 0.000 0.007 1.000 0 -1 -1 -1
MarkerName      Allele1 Allele2 Weight  Zscore  P-value Direction       HetISq  HetChiSq        HetDf   HetPVal
rs192072617       a       g       2887.00 1.579   0.1143  ++      0.0     0.032   1       0.8579
rs7929618       c       g       2887.00 -1.416  0.1568  -+      47.4    1.899   1       0.1681
rs181728325      t       c       2887.00 1.469   0.1419  ++      73.9    3.830   1       0.05033
rs7190157       a       c       2887.00 1.952   0.05088 +-      72.7    3.669   1       0.05542
rs12364336      a       g       2887.00 -1.503  0.1328  -+      69.8    3.306   1       0.06902
rs187216594       t       c       2887.00 -0.082  0.9349  +-      74.8    3.964   1       0.04649
rs12562373      a       g       2887.00 -0.290  0.7717  -+      0.0     0.150   1       0.6984
文件2:METAL1.tbl有一个标题,由制表符分隔,如下所示:

chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1
chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1
chr12-45000000-50000000 --- rs187216594 48225500 0.000 0.007 1.000 0 -1 -1 -1
MarkerName      Allele1 Allele2 Weight  Zscore  P-value Direction       HetISq  HetChiSq        HetDf   HetPVal
rs192072617       a       g       2887.00 1.579   0.1143  ++      0.0     0.032   1       0.8579
rs7929618       c       g       2887.00 -1.416  0.1568  -+      47.4    1.899   1       0.1681
rs181728325      t       c       2887.00 1.469   0.1419  ++      73.9    3.830   1       0.05033
rs7190157       a       c       2887.00 1.952   0.05088 +-      72.7    3.669   1       0.05542
rs12364336      a       g       2887.00 -1.503  0.1328  -+      69.8    3.306   1       0.06902
rs187216594       t       c       2887.00 -0.082  0.9349  +-      74.8    3.964   1       0.04649
rs12562373      a       g       2887.00 -0.290  0.7717  -+      0.0     0.150   1       0.6984
文件的行数不等,第一个文件(VDR.txt)比第二个文件(METAL1.tbl)短得多

我想:

  • 通过第一个文件(VDR.txt)的第三列和第二个文件(METAL1.tbl)的第一列合并这些文件
  • 仅保留第一个文件(VDR.txt)中的第1、2、3和4列,以及第二个文件(METAL1.tbl)中的所有列
  • 仅保留第一个文件(VDR.txt)第一列中第一个破折号前面的字符
  • 向输出文件中添加一个新列,该列重复某个字符串(例如“VDR”)
  • 输出文件不必有头,但如果有必要,最好有如下所示的头
  • 因此,我希望有一个输出文件(output.txt),其结尾如下所示:

    gene    MarkerName  chr BP  impute  Allele1 Allele2 Weight  Zscore  P-value Direction   HetISq  HetChiSq    HetDf   HetPVal
    VDR rs192072617 chr12   48225416    --- a   g   2887    1.579   0.1143  ++  0   0.032   1   0.8579
    VDR rs181728325 chr12   48225429    --- t   c   2887    1.469   0.1419  ++  73.9    3.83    1   0.05033
    VDR rs187216594 chr12   48225500    --- t   c   2887    -0.082  0.9349  +-  74.8    3.964   1   0.04649
    
    我的尝试是:

    $ awk 'FNR==NR {a[$1]=$1" "$2" "$3" "$4" "$5;next}{print $3, gensub(/-.*/, "", $1), $4, $2, a[$3]}' METAL1.tbl VDR.txt
    
    它确实以正确的方式获取了chr列和列顺序,但不幸的是,它只打印VDR.txt中需要的列,而没有打印合并文件

    我知道这是一个相当复杂的例子,任何帮助或建议都将不胜感激

    谢谢,

    Mel

    我已经对两个数据文件进行了排序,以使用
    join
    命令-这会影响输出中的行顺序-如果不需要,我可以使用另一种方法

    export LANG=C
    genef=$1
    metalf=$2
    gene=$(basename $genef .txt)
    join -13 -21 <(sort -k3,3 $genef) <(sort -k1,1 $metalf)|
    awk -vgene=$gene '
    {
      marker=$1
      chr=substr($2, 1, index($2, "-")-1)
      bp=$4
      impute=$3
      printf("%s\t%s\t%s\t%s\t%s", gene, marker, chr, bp, impute)
      for(i=12; i<=NF; ++i)
        printf("\t%s", $i)
      printf("\n")
    }
    '
    

    只要不需要标题行,它就可以直接用一个相当简单的
    awk
    脚本:

    $ awk 'FNR == NR { sub(/-.*/, "", $1); row[$3] = "VDR " $3 " " $1 " " $4 " " $2 }
    >      FNR != NR { if ($1 in row) { name = $1; $1 = ""; print row[name] $0 } }' \
    >      VDR.txt METAL1.tbl
    VDR rs192072617 chr12 48225416 --- a g 2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579
    VDR rs181728325 chr12 48225429 --- t c 2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033
    VDR rs187216594 chr12 48225500 --- t c 2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649
    $
    
    文件必须按显示的顺序列出才能正常工作

    FNR==NR
    行处理第一个文件。
    sub
    在第一个字段中删除第一个破折号及其后的所有内容;分配由
    $3
    中的标记名键入,并包含行开始的信息-固定代码、标记名、减少的染色体数、BP和标记为“插补”的破折号集

    FNR!=NR
    line处理其他文件。当列1中的值与
    数组中的一个键匹配时,从当前行中删除该键(在
    $0
    开头保留一个空白),然后打印与
    $0
    连接的
    中的值

    无需对航向线进行特殊处理;值
    MarkerName
    与第一个文件中的任何实际标记名都不匹配,因此该行将被忽略

    $ cat > test.awk
    NR==FNR {
        sub(/-.*/,"",$1)                                      # remove from 1st dash forward
        a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2               # cols 1-4 of the 1st file
        next                                        
    } 
    FNR==1 {
        printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2" # 1st part of header
    } 
    FNR==1 || $1 in a {                                       # header and matching rows
        print a[$1], $0                                       # print'em
    }
    $ awk -f test.awk VDR.txt METAL1.tbl
    H0      H3      H1      H4      H2      MarkerName      Allele1 Allele2 Weight Zscore   P-value Direction       HetISq  HetChiSq        HetDf   HetPVal
    VDR     rs192072617     chr12   48225416        ---     rs192072617     a      g2887.00 1.579   0.1143  ++      0.0     0.032   1       0.8579
    VDR     rs181728325     chr12   48225429        ---     rs181728325     t      c2887.00 1.469   0.1419  ++      73.9    3.830   1       0.05033
    VDR     rs187216594     chr12   48225500        ---     rs187216594     t      c2887.00 -0.082  0.9349  +-      74.8    3.964   1       0.04649
    
    作为一个班轮:

    awk 'NR==FNR { sub(/-.*/,"",$1); a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2; next} FNR==1 {printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2"} FNR==1 || $1 in a {print a[$1], $0}' VDR.txt METAL1.tbl
    

    你有没有试图解决这个问题?如果是这样,你应该分享这个。以“这是我的规格,请为我编码”的形式提出的问题通常不受欢迎,但以“这是我的代码,这是我遇到问题的部分”的形式提出的问题是。文件中的字段是如何识别的?固定宽度?或者分隔符是什么?我建议将数据样本减少到4列左右(刚好足以解决根本问题)。您是否知道unix/linux命令
    join
    ?如果您可以使用分隔数据(如
    |
    或tab),您可能可以在一行中完成您想要的操作。但是我没有仔细查看您的输入和输出(因为它们太宽;-),所以我可能是错的。祝你好运。你真的需要简化或澄清你的项目符号(3)只保留第一个文件(VDR.txt)第一列中第一个破折号之前的字符——在第一个破折号之前,而不是在前4个破折号之前,以避免染色体数小于10的破折号(例如,不希望有chr7,但要有chr7)。您的示例数据没有
    chr7
    引用,因此不清楚这是怎么回事。从
    chr12-45000000-50000000
    类型名称中获取
    chr12
    很容易理解,但是您只是想从
    chr7-45000000-50000000
    中获取
    chr7
    ?“你既没有演示也没有解释这个额外的皱纹。”乔纳坦利弗勒我简化了子弹3。很抱歉造成混淆,我想写一个多功能的函数,可以用于其他可能有一些差异的文件。(但不幸的是,我有点懒得给出正确的例子)--也非常感谢您提供的解决方案,效果很好,速度也很快!并添加
    BEGIN{print“header you want”}
    非常感谢您的帮助,这非常有效,但我正在寻找类似Jonathan Leffler的解决方案的一行程序。感谢您的建议,但我不喜欢
    join
    的原因是我必须订购文件。。。对于第一个文件(VDR.txt),这将是一项简单的任务,但对于第二个文件(METAL1.tbl),这是一个相当大的文件(约600 Mb)。排序METAL1.tbl只是不断给我错误,增加了更多的处理时间,这就是为什么我一直在寻找一个解决方案围绕awk。好的点-排序600MB是相当快的-但一个单一的通过awk总是好的-你看到什么错误与排序?