Isso deve funcionar como esperado:
awk '/>chr/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' file
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
Eu tenho um arquivo como este
>chr1
ACGTGGC
TGCCGTT
ATCCTTG
>chr2
ACTTTTA
CTCATAA
Eu quero converter o seq em uma string. Esta deve ser a saída:
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
Como posso fazer isso usando o awk? Eu sei como fazer isso em Perl.
Obrigado
Isso deve funcionar como esperado:
awk '/>chr/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' file
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
awk 'BEGIN{ RS=">[^\n]+\n"; }
NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }
{ rt=RT; }' myfile
Saída:
>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA
Para referência geral: Usando dados de entrada do exemplo de formato FASTA e repetindo-o para fazer um arquivo de teste 81,1 MB , recebi os seguintes resultados time
:
Peter.O real 0m1.653s user 0m1.396s sys 0m0.256s
user2196728 real 0m6.587s user 0m5.972s sys 0m0.252s
kos real 0m12.866s user 0m12.589s sys 0m0.268s
Os md5sum
de todos os métodos testados foram os mesmos. A versão de user2196728
precisou de >chr
alterado para apenas >
para funcionar de forma mais geral.
Como você está usando um formato de arquivo muito específico, presumi que o primeiro registro está sempre na forma de ><string>
:
< inputfile awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END {print x}' > outputfile
Expandido:
NR==1 {
print;
next
}
!/>/ {
x=x$0;
next
}
/>/ {
print x"\n"$0;
x="";
next
}
END {
print x
}
>
não corresponder ao registro atualmente processado: ele concatena o conteúdo do registro atualmente processado para a variável x
e pula para o próximo registro; >
corresponder ao registro atualmente processado: ele imprime o conteúdo da variável x
imediatamente seguida por um caractere de nova linha imediatamente seguido pelo conteúdo do registro atualmente processado e ignora para o próximo registro; x
; Eu testei todas as respostas para essa pergunta verificando o md5sum
dos arquivos de saída em um SSD logo após a inicialização do sistema e depois de ter emitido o comando sudo fstrim -v /
, usando o seguinte script bash
, onde outputfile
é um arquivo ~ 226MB criado pela repetição do arquivo em este link 100000 vezes:
#!/bin/bash
for ((i=0; i<3; i++)); do /usr/bin/time -f "kos\t\treal %e" awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END{print x}' outputfile > outputfile1; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "Peter.O\t\treal %e" awk 'BEGIN{ RS=">[^\n]+\n"; }NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }{ rt=RT; }' outputfile > outputfile2; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "user2196728\treal %e" awk '/>/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' outputfile > outputfile3; done
md5sum outputfile1 outputfile2 outputfile3
Estes são os resultados:
~$ sudo fstrim -v /
[sudo] password for user:
/: 68,8 GiB (73839202304 bytes) trimmed
~$ cd tmp
~/tmp$ bash exe
kos real 2.55
kos real 2.57
kos real 2.55
Peter.O real 2.93
Peter.O real 2.92
Peter.O real 2.92
user2196728 real 2.51
user2196728 real 2.51
user2196728 real 2.68
0618a8077b43eb44eb263d7d6f84777f outputfile1
0618a8077b43eb44eb263d7d6f84777f outputfile2
0618a8077b43eb44eb263d7d6f84777f outputfile3
Tags awk