awk manipulação do arquivo fasta

2

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

    
por user3138373 17.06.2015 / 00:34

3 respostas

1

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
    
por 17.06.2015 / 01:19
1
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.

    
por 17.06.2015 / 01:34
1

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
}
  • O primeiro bloco é executado apenas se o número de registro atualmente processado for 1: ele imprime o registro atualmente processado e pula para o próximo registro;
  • O segundo bloco é executado apenas se a expressão regular > 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;
  • O terceiro bloco é executado somente se a expressão regular > 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;
  • O quarto bloco é executado apenas se não houver mais registros para processar: ele imprime o conteúdo da variável 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
    
por 17.06.2015 / 01:34

Tags