이런 파일이 있어요
>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