Eu ainda não entendi completamente sua explicação e saída desejada (por que alguns valores da coluna 1 chr1
e alguns ch1
? por que a coluna 2 na primeira linha 820983 ao invés de 860759?), no entanto isso pode ser o suficiente para você começar.
Se você não se importa com a ordem de saída, a coisa mais simples parece ser inverter a ordem das linhas no arquivo, e então simplesmente manter um registro contínuo dos valores mais recentes da coluna 2 para o +
e -
entradas, e imprima / subtraia-as quando o próximo +
ou -
for encontrado:
$ tac file.bed | awk '
> $NF ~ /+/ {if(last2p) print $1, last2p, "(" last2p "-" $3 ")", $4, $5, $6; last2p = $2}
> $NF ~ /-/ {if(last2m) print $1, last2m, "(" last2m "-" $3 ")", $4, $5, $6; last2m = $2}
> '
chr1 860759 (860759-820983) ENSG00000269308 591 +
chr1 738637 (738637-623056) ENSG00000185097 589 -
chr1 818542 (818542-369634) ENSG00000235249 587 +
chr1 621546 (621546-140379) ENSG00000237683 586 -
Se você fizer se preocupar com a ordem de saída, então você pode construir um par de arrays plus
e minus
, depois iterar sobre eles na ordem inversa procurando "up" para a próxima correspondência +
ou -
. Isso é muito grande para um one-liner, apresentado aqui como um script awk executável:
$ cat chr.awk
#!/usr/bin/gawk -f
function fooprint(a,i, j,p,q) {
split(a[i], p);
for(j=i-1;j>0;j--) {
if(j in a) {
split(a[j], q);
print q[1], p[2], "(" p[2] "-" q[3] ")", q[4], q[5], q[6];
break;
}
}
}
$NF ~ /+/ {plus[FNR] = $0}
$NF ~ /-/ {minus[FNR] = $0}
END {
for(i=NR; i>1; i--) {
if (i in plus)
fooprint(plus,i);
else if (i in minus)
fooprint(minus,i);
}
}
então
$ ./chr.awk file.bed
chr1 860759 (860759-820983) ENSG00000269308 591 +
chr1 818542 (818542-369634) ENSG00000235249 587 +
chr1 738637 (738637-623056) ENSG00000185097 589 -
chr1 621546 (621546-140379) ENSG00000237683 586 -