awk는 fasta 파일을 운영합니다.

awk는 fasta 파일을 운영합니다.

이런 파일이 있어요

>chr1
ACGTGGC
TGCCGTT
ATCCTTG
>chr2
ACTTTTA
CTCATAA

seq를 1개의 문자열로 변환하고 싶습니다. 다음과 같이 출력되어야 합니다.

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

awk를 사용하여 어떻게 이를 수행할 수 있습니까? 저는 Perl로 이 작업을 수행하는 방법을 알고 있습니다.

감사해요

답변1

예상대로 작동합니다.

awk '/>chr/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' file

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

답변2

awk 'BEGIN{ RS=">[^\n]+\n"; } 
     NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }
     { rt=RT; }' myfile

산출:

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

일반적인 참고 사항: 다음의 입력 데이터를 사용합니다.FASTA 형식의 예, 그리고 이를 반복하여81.1MB파일을 테스트한 결과 다음과 같은 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

결과는 모든 테스트 방법에서 md5sum동일합니다 . 보다 일반적 으로 작동하려면
user2196728버전을 변경해야 합니다 .>chr>

답변3

매우 구체적인 파일 형식을 사용하고 있으므로 첫 번째 레코드는 항상 다음과 같은 형식이라고 가정합니다 ><string>.

< inputfile awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END {print x}' > outputfile

확장:

NR==1 {
    print;
    next
}
!/>/ {
    x=x$0;
    next
}
/>/ {
    print x"\n"$0;
    x="";
    next
}
END {
    print x
}
  • 첫 번째 블록은 현재 처리 중인 레코드 번호가 1인 경우에만 실행됩니다. 현재 처리 중인 레코드를 인쇄하고 다음 레코드로 점프합니다.
  • 두 번째 블록은 정규식이 현재 처리된 레코드와 일치하지 않는 경우에만 실행됩니다 >. 현재 처리된 레코드의 내용을 변수에 연결 x하고 다음 레코드로 점프합니다.
  • 세 번째 블록은 정규식이 현재 처리된 레코드와 일치하는 경우에만 실행됩니다 >. 변수의 내용 x, 개행 문자, 현재 처리된 레코드의 내용이 차례로 인쇄되고 다음 레코드로 점프합니다.
  • 네 번째 블록은 처리할 레코드가 더 이상 없을 때만 실행됩니다. 변수의 내용을 인쇄합니다 x.

md5sum나는 시스템 시작 직후 SSD의 출력 파일을 확인하고 다음 위치에서 파일을 반복하여 ~226MB 파일을 생성하는 sudo fstrim -v /다음 bash스크립트를 사용하여 명령을 실행한 후 이 질문에 대한 모든 답변을 벤치마킹했습니다.outputfile이 링크100,000회:

#!/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

결과는 다음과 같습니다.

~$ 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

관련 정보