根据两个文件的第一列比较两个制表符分隔的文件,并在输出文件中打印匹配和不匹配的条目

根据两个文件的第一列比较两个制表符分隔的文件,并在输出文件中打印匹配和不匹配的条目

我有两个制表符分隔的文件(fileA.txt 和 fileB.txt),我必须将 fileA.txt 的第一列与 fileB.txt 的第一列进行比较,并且我想打印第二列中存在的值输出文件中的 fileB.txt。下面是我的

fileA.txt

id
chr1_45796849_A_T
chr1_45796854_C_T
chr1_45797174_T_A
chr1_45796852_G_C
chr19_9018540_A_G
chr19_9002576_T_C
chr1_45797487_A_G
chr1_45797153_A_T
chr1_45797750_C_T

FileB.txt

chr_pos             freq.var
chr1_45796849_A_T   0.028399811
chr1_45796852_G_C   0.019154034
chr1_45796854_C_T   0.015872901
chr1_45797153_A_T   0.010129176
chr1_45797487_A_G   0.012981216
chr1_45797750_C_T   0.024949931

以下是预期结果

id                  freq.var
chr1_45796849_A_T   0.028399811
chr1_45796854_C_T   0.015872901
chr1_45797174_T_A   
chr1_45796852_G_C   0.019154034
chr19_9018540_A_G   
chr19_9002576_T_C   
chr1_45797487_A_G   0.012981216
chr1_45797153_A_T   0.010129176
chr1_45797750_C_T   0.024949931

我已经提到过awk - 比较 2 个文件的 2 列并打印公共行但它只给出匹配的条目

答案1

首先阅读fileB.txt,将第一个字段设为键,将第二个字段设为数组中的值,使用FNR>1(跳过标题行NR 和 FNR 是什么?“NR==FNR”意味着什么?)。

然后读取fileA.txt,打印第一行的标题,然后打印其第一个字段,后跟数组中的相应元素(如果有)。

awk '
    FNR==NR && FNR>1{a[$1]=$2}
    NR!=FNR{
        if(FNR>1){print $1,a[$1]}
        else{print "id", "freq.var"}
    }
' OFS="\t" fileB.txt fileA.txt

OFS="\t"将输出字段分隔符设置为制表符。由于您的文件是制表符分隔的,我假设输出文件也应该是制表符分隔的。

您可以通过管道将其输入column -t以进行对齐。

答案2

如果您不需要保留原始排序顺序,可以使用join

$ join -a1 -j1 -t$'\t' <(tail -n+2 fileA.txt | sort)  <(tail -n+2 fileB.txt | sort)
chr1_45796849_A_T   0.028399811
chr1_45796852_G_C   0.019154034
chr1_45796854_C_T   0.015872901
chr1_45797153_A_T   0.010129176
chr1_45797174_T_A
chr1_45797487_A_G   0.012981216
chr1_45797750_C_T   0.024949931
chr19_9002576_T_C
chr19_9018540_A_G

或者,保留标题:

$ ( printf 'id\tfreq.var\n'; join -t$'\t' -a1 -j1 <(tail -n+2 fileA.txt | sort)  <(tail -n+2 fileB.txt | sort))
id  freq.var
chr1_45796849_A_T   0.028399811
chr1_45796852_G_C   0.019154034
chr1_45796854_C_T   0.015872901
chr1_45797153_A_T   0.010129176
chr1_45797174_T_A
chr1_45797487_A_G   0.012981216
chr1_45797750_C_T   0.024949931
chr19_9002576_T_C
chr19_9018540_A_G

并漂亮地打印:

$ ( printf '%-20s\t%s\n' "id" "freq_var"; join -t$'\t' -a1 -j1 <(tail -n+2 fileA.txt | sort)  <(tail -n+2 fileB.txt | sort))
id                      freq_var
chr1_45796849_A_T   0.028399811
chr1_45796852_G_C   0.019154034
chr1_45796854_C_T   0.015872901
chr1_45797153_A_T   0.010129176
chr1_45797174_T_A
chr1_45797487_A_G   0.012981216
chr1_45797750_C_T   0.024949931
chr19_9002576_T_C
chr19_9018540_A_G

答案3

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR {
    map[(NR>1 ? $1 : "id")] = $2
    next
}
{ print $1, map[$1] }
$ awk -f tst.awk fileB fileA
id  freq.var
chr1_45796849_A_T   0.028399811
chr1_45796854_C_T   0.015872901
chr1_45797174_T_A
chr1_45796852_G_C   0.019154034
chr19_9018540_A_G
chr19_9002576_T_C
chr1_45797487_A_G   0.012981216
chr1_45797153_A_T   0.010129176
chr1_45797750_C_T   0.024949931

答案4

GNU sed扩展正则表达式模式开启-E且无自动打印-n。首先读入fileB并将其存储在保留空间中。然后对文件 A 的每一行进行比较,是否发现处于保留状态。

sed -En '
  1{
    s/^\S+/id/
    :filea
      H;n
    /\t/b filea
    x;s/$/\n/;x
  }
  G
  s/^([^\n]+)\n.*\n(\1\t[^\n]*)\n.*/\2/p;t
  s/\n.*/\t/p
' fileB.txt fileA.txt

结果:

id  freq.var
chr1_45796849_A_T   0.028399811
chr1_45796854_C_T   0.015872901
chr1_45797174_T_A   
chr1_45796852_G_C   0.019154034
chr19_9018540_A_G   
chr19_9002576_T_C   
chr1_45797487_A_G   0.012981216
chr1_45797153_A_T   0.010129176
chr1_45797750_C_T   0.024949931

相关内容