awk를 사용하여 대용량 파일을 구문 분석하고 하위 집합을 추출합니다.

awk를 사용하여 대용량 파일을 구문 분석하고 하위 집합을 추출합니다.

아래와 같이 큰 파일이 있습니다.

chr10   98072   1
chr10   98073   1
chr10   98074   1
chr10   98075   2
chr10   98076   2
chr10   98077   3
chr10   98078   5
chr10   98079   5
chr11   98080   5
chr12   98081   5

각 염색체마다 많은 항목이 있습니다. chr10이 포함된 행만 추출하고 싶습니다. 내 파일이 크기 때문에 이 명령을 사용하여 chr10 줄만 추출합니다.

awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt > subset.txt

awk가 전체 파일을 반복하지 않도록 하는 좋은 방법입니까? 내 파일은 염색체에 따라 정렬되었습니다.

감사해요

답변1

awk '$1=="chr10"{print; next}{exit}' cov.txt > subset.txt

테스트: /dev/null다음 으로 리디렉션12,947,909 chr10기록에 더해 총 몇 가지 기록 chr11추가chr1299,063,774행 - 출력은 모두 동일합니다(동일한 md5sum). 출력 라인 수 =12,947,909-- 가장 빠른 것부터 가장 느린 것까지 정렬:

스티브:awk '{ if($1 == "chr10") { print } else { exit } }' cov.txt >/dev/null

real  0m5.963s
user  0m5.896s
sys   0m0.064s

피터 오:awk '$1=="chr10"{print; next}{exit}' cov.txt >/dev/null

real  0m6.553s
user  0m6.484s
sys   0m0.068s

코스:perl -pe '!/chr10/&&exit' cov.txt >/dev/null

real  0m8.658s
user  0m8.545s
sys   0m0.112s

스티브:sed -n '/^chr10[^0-9]/ { p; b; }; q' cov.txt >/dev/null

real  0m17.130s
user  0m17.077s
sys   0m0.052s

사용자 3138373:awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt >/dev/null

real  0m18.621s
user  0m18.541s
sys   0m0.080s

답변2

이것을 시도해 보세요. 기본 테스트에서는 조금 더 빠른 것 같습니다. 정규식 처리를 피하세요.

[root@localhost tmp]# wc -l cov.txt
34970568 cov.txt
[root@localhost tmp]# time awk '$1 ~ /^chr10$/{print}; $1 !~ /^chr10$/{exit}' cov.txt > subset.txt

real    0m23.897s
user    0m22.031s
sys     0m1.556s
[root@localhost tmp]# time awk '{ if($1 == "chr10") { print } else { exit } }' cov.txt > subset.txt

real    0m16.784s
user    0m14.731s
sys     0m1.661s
[root@localhost tmp]#

또한 lcd047 타이밍의 sed 방법을 시도했습니다.

[root@localhost tmp]# time sed -n '/^chr10[^0-9]/ { p; b; }; q' cov.txt > subset.txt

real    0m38.343s
user    0m36.609s
sys     0m1.546s
[root@localhost tmp]#

전체 파일을 읽더라도 일반 오래된 grep을 사용하는 것이 가장 빠릅니다.

[root@localhost tmp]# time grep "^chr10" cov.txt >subset.txt

real    0m6.546s
user    0m4.932s
sys     0m1.577s
[root@localhost tmp]#

나는 grep -F가 다시 더 빨라질 것이라고 생각했지만 그렇지 않은 것 같습니다. 7초 이상 지속됩니다.

[root@localhost tmp]# time grep -F chr10 cov.txt >subset.txt

real    0m7.317s
user    0m6.109s
sys     0m1.173s
[root@localhost tmp]#

답변3

보다 효율적으로 다음을 수행하십시오 egrep.

egrep '^chr10{space or tab}' cov.txt

또는 콘텐츠가 귀하가 보여주고 있는 것과 유사하다면,

grep -w chr10 cov.txt

답변4

파일이 정렬되어 있으므로귀하의 의견Perl로 시작하는 줄은 chr10항상 파일의 시작 부분에 있습니다.

< cov.txt perl -pe '!/chr10/&&exit' > subset.txt

이렇게 하면 첫 번째 불일치 시 스크립트가 종료됩니다.

메모리에 저장된 1,000,000개의 일치하는 라인이 있는 파일 chr10 98072 1에 대한 테스트 실행 (빈 파일에 라인을 1,000,000번 추가하여 얻은 결과)은 즉시 실행됩니다.

~/tmp$ < cov.txt wc -l
1000000
~/tmp$ time < cov.txt perl -pe '!/chr10/&&exit' > subset.txt

real    0m0.631s
user    0m0.624s
sys 0m0.004s
~/tmp$ < subset.txt wc -l
1000000

관련 정보