2019년 9월 3일 화요일

간단한 AWK 활용 팁 - 컬럼 수의 총 합계 구하기 등

QIIME에서 사용하기에 좋은 매우 간단한 awk 활용 예제를 소개해 본다. OTU map file은 similarity에 의해 묶인 서열의 클러스터를 표현한 tab-delimited text file이다. 한 줄은 하나의 클러스터이며 맨 왼쪽은 클러스터의 ID, 나머지 컬럼은 클러스터를 이루는 각 서열의 ID이다.


총 몇 개의 서열이 클러스터를 이루는 것일까? awk가 이를 간단하게 계산해 준다.

$ awk 'BEGIN{s=0}{s+=NF-1}END{print s}' final_otu_map.txt

NF는 awk의 내장 함수로서 컬럼의 수를 의미한다. 첫번째 컬럼은 클러스터 ID므로 NF에서 하나를 뺀 것을 더해나간 뒤(변수 s에 저장), 파일의 모든 라인에 대한 처리가 끝나면 인쇄를 하면 된다.

다음은 조건에 맞는 줄은 편집을 하고, 그렇지 않은 줄은 그대로 출력하는 방법을 알아본다. 작년에 'awk를 이용한 같단한 텍스트 파일 조작(join)'이라는 제목의 글로 그 기본 원리에 대해서 이미 포스팅을 한 적이 있었다. 다음은 Gopalakrishnan의 2018년도 Science 논문에서 다룬 16S rRNA sequencing 결과 중 하나인 ERR2162226의 일부를 표시한 것이다.


엄밀히 말하자면 이 파일은 MiSeq가 생산한 그대로의 파일이 아니다. Wargo.R2d2_45029를 서열 ID로 전환하는 것이 오늘의 목표이다. '/1'은 제거해야 한다.

Awk를 사용하면 다음과 같이 명령행 한 줄로 끝난다.


$ awk '/^@ERR2162226/{printf "%s%s\n", "@", substr($2,1,length($2)-2);next}{print}' ERR2162226.fastq > ERR2162226-mod.fastq

awk '조건{명령A; next}{명령 B}' 텍스트파일

이 명령을 이해하는 것이 핵심이다. 조건에 맞으면 A를 실행한 뒤 next를 통해서 뒷쪽의 {명령B} 블록을 건너뛰고, 조건에 맞지 않으면 곧바로 {명령B}를 실행한다. if..else에 해당하는 문법이 아니다!. 만약 next가 없으면, 조건에 맞는 줄에서 명령A를 실행한 뒤, 그 줄에 대해서 또, 명령 B를 실행하게 된다. 이것을 가지고서 fasta로 전환한 뒤(split_libraries_fastq.py의 -q 19 옵션을 적용하여 quality에 의해 필터링하는 것을 똑같이 구현하려면 쉽지는 않음) pick_otus.py 명령을 실행하여 실습을 진행하면 된다.

awk의 printf 함수와 substr 함수의 용법도 이번에 공부를 해 두면 도움이 될 것이다.

댓글 없음: