在awk中合并和处理2个制表符分隔的文件,然后制作一个新文件

时间:2019-02-06 11:07:09

标签: awk

我有2个带有2列的tab separated文件。第1列是数字,第2列是ID。像下面两个例子一样:

示例文件1:

188 TPT1
133 ACTR2
420 ATP5C1
942 DNAJA1

示例文件1:

91  PSMD7
2217    TPT1
223 ATP5C1
156 TCP1

我想根据第2列(列ID)找到2个文件的公共行,并创建一个新的制表符分隔文件,其中有4列:column1是ID(公共ID)column2是file1中的编号,column3是file2中的数字,column4是第2列和第3列之比的log2值(表示log2(column2 / column3))。例如,关于ID“ TPT1”:第1列是TPT1,第2列是188,第3列是2217,第4列是log2(188/2217),它等于-3.561494。 这是预期的输出:

预期输出:

TPT1    188 2217    -3.561494
ATP5C1  420 223 0.9133394

我正在尝试使用以下代码在AWK中做到这一点:

awk 'NR==FNR { n[$2]=$0;next } ($2 in n) { print n[$2 '\t' $1] '\t' $1 '\t' log(n[$1]/$1)}' file1.txt file2.txt  > result.txt

此代码未返回我期望的结果。你知道如何解决吗?

3 个答案:

答案 0 :(得分:1)

$ awk -v OFS="\t" 'NR==FNR {n[$2]=$1;next} ($2 in n) {print $2, $1, n[$2], log(n[$2]/$1)/log(2)}' file1 file2 
TPT1    2217    188  -3.5598
ATP5C1  223     420  0.913346

答案 1 :(得分:0)

我会使用join实际合并文件,而不是awk:

$ join -j2 <(sort -k2 file1.txt) <(sort -k2 file2.txt) |
   awk -v OFS="\t" '{ print $1, $2, $3, log($2/$3)/log(2) }'
ATP5C1  420 223 0.913346
TPT1    188 2217    -3.5598

join程序可以将两个文件连接到一个公共值。它确实需要根据连接列对文件进行排序,但是您的示例不是必需的,因此数据文件的内联sort排序。然后将其输出通过管道传输到awk,以计算每行数字的log2并产生制表符分隔的结果。


使用perl的替代方法,如果您关心的话,它可以为您提供更多的默认精度(并且不想弄混awk的CONVFMT变量):

$ join -j2 <(sort -k2 a.txt) <(sort -k2 b.txt) |
   perl -lane 'print join("\t", @F, log($F[1]/$F[2])/log(2))'
ATP5C1  420 223 0.913345617745818
TPT1    188 2217    -3.55980420318967

答案 2 :(得分:0)

awk +排序方法

 awk ' { print $0,FILENAME }' ellyx.txt ellyy.txt | sort -k2 -k3 | awk ' {c=$2;if(c==p) { print c,a,$1,log(a/$1)/log(2) }p=c;a=$1 } '

具有给定的输入

$ cat ellyx.txt
188 TPT1
133 ACTR2
420 ATP5C1
942 DNAJA1

$ cat ellyy.txt
91  PSMD7
2217 TPT1
223 ATP5C1
156 TCP1

$ awk ' { print $0,FILENAME }' ellyx.txt ellyy.txt | sort -k2 -k3 | awk ' {c=$2;if(c==p) { print c,a,$1,log(a/$1)/log(2) }p=c;a=$1 } '
ATP5C1 420 223 0.913346
TPT1 188 2217 -3.5598

$