我有两个已排序的制表符分隔文件。
input.txt
10 282035 282125 RNA1 -
10 4134522 4134564 RNA1 -
10 5299783 5299910 RNA2 -
10 5900317 5900359 RNA1 -
ref.txt
1 9 137792944
1 9 137792945
1 10 282074
4 10 282095
4 10 5900329
如果满足某些条件,我想打印值的总和。
即:
IF 参考$2==输入$1
和
ref$3 落在 min==input$2 && max==input$3 的范围内
打印 input$0 和 ref$1 的总和(作为 input$6),否则打印零(作为 input$6) 所以结果应该如下所示:
10 282035 282125 RNA1 - 5
10 4134522 4134564 RNA1 - 0
10 5299783 5299910 RNA2 - 0
10 5900317 5900359 RNA1 - 4
这就是我想出的:
awk '
NR == FNR {min[NR]=$2; max[NR]=$3; chr[NR]=$1; next}
{
for (id in min)
if (($2==chr[NR])&&(min[id] < $3 && $3 < max[id])) {
print $0, sum+=$1
break
}
}
' input.txt ref.txt > output.txt
这里显然有问题,因为我没有得到任何输出。另外,我仍然缺少“否则打印零”。
有人可以帮我吗?
答案1
这使用 GNU awk,它允许嵌套数组:
gawk '
NR == FNR {
ref[$2][$3] = $1
next
}
$1 in ref {
sum = 0
for (key in ref[$1])
if ($2 <= key && key <= $3)
sum += ref[$1][key]
print $0, sum
}
' ref.txt input.txt
答案2
awk 'NR==FNR {dat[NR]=$0;next} { for ( i in dat ) { split(dat[i],arr," ");tag=arr[1];min=arr[2];max=arr[3];if ($2==tag && $3 <= max && $3 >= min) { res[i]+=$1 } } } END { for (i in dat) { print dat[i]" "(res[i]!=0?res[i]:"0") } }' input ref
awk 'NR==FNR {
dat[NR]=$0;next
}
{ for ( i in dat ) {
split(dat[i],arr," ")
tag=arr[1];
min=arr[2];
max=arr[3];
if ($2==tag && $3 <= max && $3 >= min) {
res[i]+=$1
}
}
}
END {
for (i in dat) {
print dat[i]" "(res[i]!=0?res[i]:"0")
}
}' input ref
将 input.txt 的每一行放入一个数组中。然后获取 ref.txt 的每一行并使用 awk 函数 split 将额外数据放入数组 arr 中。从这个数组中我们获得变量标签、最小值和最大值。然后根据条件检查数组 dat 的每一行,并且数组 res 相应地递增。最后,dat 循环打印数据以及 res 中的计数。
结果:
10 5900317 5900359 RNA1 - 4
10 282035 282125 RNA1 - 5
10 4134522 4134564 RNA1 - 0
10 5299783 5299910 RNA2 - 0