2019년 7월 12일 금요일

grep의 현명한 사용법 - 검색할 패턴(파일로 제공)이 없는 라인을 출력하기

grep은 텍스트 파일 혹은 표준 입력으로부터 주어진 패턴이 존재하는 라인을 출력하는 유틸리티이다. 검색할 패턴은 보통 명령행 옵션으로 하나가 주어진다. 그런데 찾아야 할 패턴이 여러개라면, 이를 별도의 파일('FILE')로 지정해 놓고 -f FILE 옵션으로 제공하면 된다. 검색할 패턴은 FILE 내에서 각각 별도의 라인으로 저장되어 있어야 한다. 좀 더 유식하게 말하자면 FILE 내에서 newline(개행 문자 혹은 쉬운 우리말로는 새줄 문자)로 패턴들이 분리되어 있어야 한다.

이와는 반대로, 특정 패턴이 없는 라인만을 파일에서 출력하고 싶다면? 패턴이 하나라면 -v(--invert-match) 옵션을 사용하면 된다. 그렇다면 좀 더 복잡한 상황을 가정해 보자. 배제하고 싶은 패턴이 여럿이라면 어떻게 하면 되나?

ftp://ftp.ncbi.nlm.nih.gov/genomes/refseq/bacteria/assembly_summary.txt 파일을 다운로드하여 내가 연구하는 어떤 미생물종에 해당하는 라인만을 골라내어 별도로 저장했다고 가정하자(my_species_summary.txt). 그런데 상세히 조사를 해 보니 어떤 레코드는 assembly가 불량하여 배제를 해야 되겠다고 마음을 먹었다. 배제할 레코드의 assembly accession(GCF_로 시작하는)을 따로 추려서 REJECTION이라는 텍스트 파일에 저장을 하였다. my_species_summary.txt에서 이 억세션에 해당하는 라인만을 제외한 나머지를 출력하려면 이렇게 하면 된다.

grep -Fv -f <(cat REJECTION) my_species_summary.txt

-F (--fixed-strings, --fixed-regexp)가 열쇠를 쥐고 있다. grep 매뉴얼에 의하면, -F 옵션은 newline으로 분리된 패턴을 일종의 목록으로 간주하여 각각에 대하여 매치 작업을 하는 것이다. 이것이 -v와 결합된 상태이니 딱 내가 바라는 작업을 할 수 있는 것이다.

힌트는 다음의 웹페이지에서 얻었다.

[Stack Overflow] Search multiple pattern in file and delete line if pattern matches

댓글 없음: