我遇到的问题超出了我的基本unix知识,非常感谢一些帮助。我有一个大文件,格式如下:
chr1 10495 10499 211
chr1 10496 10500 1
chr1 10587 10591 93
chr1 10588 10592 1
chr1 10639 10643 4
chr1 10668 10672 11
chr1 10697 10701 13
chr1 10726 10730 8
chr1 10755 10759 7
chr1 10784 10788 5
chr2 10856 10860 4
chr3 10932 10936 6
chr3 10933 10937 2
chr5 11056 11060 4
chr6 11155 11159 9
如果第一列中的值与第二列中的一个数字差异匹配,我想要将两行中第4列的值相加,并将第1行中第3列的值替换为第2行中第3列的值,否则只是唯一行中的值而不修改任何列。
所以我希望的输出看起来像这样:
chr1 10495 10500 212
chr1 10587 10592 94
chr1 10639 10643 4
chr1 10668 10672 11
chr1 10697 10701 13
chr1 10726 10730 8
chr1 10755 10759 7
chr1 10784 10788 5
chr2 10856 10860 4
chr3 10932 10937 8
chr5 11056 11060 4
chr6 11155 11159 9
答案 0 :(得分:2)
{{1}}
答案 1 :(得分:1)
没有仔细检查过,但我认为你想要:
awk '{split(p,a)}
$1==a[1] && a[2]==$2-1{print a[1], a[2], $3, $4 + a[4]; p=""; next}
p {print p} {p=$0}
END {print}' OFS=\\t input
在任何给定的步骤(第一步除外),p
保存前一行的值。脚本的第二行检查当前行中的第一个字段是否与最后一行的第一个字段匹配,第二个字段是否大于最后一行的第二个字段。在这种情况下,它打印前一行的前两个字段,第三个从当前行打印,以及第四个字段的总和,然后移动到下一行。如果它们不匹配,则打印上一行。最后,它只是打印线。
答案 2 :(得分:0)
这个脚本,我用来合并转录组数据中的间隔
awk '
NR==1{
n= split($0, first);
c=1;
for(i=1; i<=n; i++) d[c, i] = first[i];
}
NR>1{
n= split($0, actual);
#if(actual[1] != d[c, 1] || actual[2]>d[c, 3]){ #for interval fusion
if(actual[1] != d[c, 1] || actual[2]>d[c,2]+1){ #OP requirement
c++;
for(i=1; i<=n; i++) d[c, i] = actual[i];
}else{
if(actual[3] > d[c,3]) d[c,3] = actual[3];
d[c,4] = d[c,4] + actual[4];
}
}
END{
for(i=1; i<=c; i++){
print d[i, 1], d[i, 2], d[i, 3], d[i, 4]
}
}' file
你得到:
chr1 10495 10500 212 chr1 10587 10592 94 chr1 10639 10643 4 chr1 10668 10672 11 chr1 10697 10701 13 chr1 10726 10730 8 chr1 10755 10759 7 chr1 10784 10788 5 chr2 10856 10860 4 chr3 10932 10937 8 chr5 11056 11060 4 chr6 11155 11159 9