SED 를 이용한 텍스트 파일 핸들링

SED란?

SED 는 유닉스 계열 운영체제 (Linux, OSX, Solaris 등등) 라면 기본적으로 어디에나 있는 기본 유틸리티로써, 정규표현식을 이용하여 간편하게 패턴을 검색하고 이를 이용하여 파일을 수정하는데 매우 유용한 유틸리티이다. 물론 펄이나 파이썬으로 스크립트를 짜서 할 수도 있지만, 치환문 하나로 끝나는 단순한 일이라면 SED가 제격이다.

SED 는 이름 그대로 '스트림 에디터' 이므로 다른 명령어의 결과물인 표준 출력물을 필터를 통해 받아서 이를 프로세싱하는 식으로 작동하게 된다. SED에서 가장 많이 사용되는 치환 명령의 문법은

sed 's/검색 패턴/치환될 문자열/'


여기서 검색 패턴은 단순한 문자열이 될 수도 있고 정규식 (Regular Expression) 이 될 수도 있다. 아마 vi와 같은 에디터에서 치환 기능을 사용해 본 사람이라면, 상대적으로 쉽게 개념을 이해할 수 있을 것 같다.

이제 아주 간단한 예를 들어보도록 하자.



우리의 소원은 통일
꿈에도 소원은 통일
이나라 살리는 통일
통일을 이루자


이런 내용의 텍스트 파일이 unify.txt라는 이름으로 저장되어 있고, 다음과 같은 명령을 내리면



cat unify.txt | sed 's/통일/분단/'


이런 내용이 표준 출력으로 출력된다.


우리의 소원은 분단
꿈에도 소원은 분단
이나라 살리는 분단
분단을 이루자


통일부도 없어지는 와중에 좀 심했나. ㅠㅠ

물론 이런 것은 노트패드의 치환 기능으로도 할 수 있는 것이긴 하지만서도. -.-;;
일단은 sed 의 가장 기본적인 작동 방식을 보여주는 하나의 예라고 생각하기 바란다.

활용예

SED에 대해서 조금 더 자세한 설명은 여기를 참고하는 것이 좋겠고, 여기서는 '특정업계' 종사자를 위한 실질적인 예를 들도록 하자.

분자생물학을 하는 사람이라면 대개 자신이 연구하는 단백질과 homolog 들간의 Multiple Sequence Alignment (이하 MSA) 를 만들어 본 경험이 있을 것이다. 가령 BLAST를 통해 얻은 다음과 같은 Multifasta file을 이용하여 MSA를 만든다고 해 보자.


sequences.fasta

그런데 여기서  단백질의 이름이나 accession number  등은 다 빼버리고 생물종의 이름만을 제목으로 쓰고 싶다면? 어차피 위의 예는 서로 다른 생물 유래의 동일한 종류의 단백질이기 때문이다.

즉,
>gi|15679284|ref|NP_276401.1| aspartyl/glutamyl-tRNA amidotransferase subunit B [Methanothermobacter thermautotrophicus str. Delta H]
를,
>Methanothermobacter thermautotrophicus str.Delta H

과 같은 식으로 만들고 싶다면?

물론 대다수의 생물학 전공자들은 '노트패드를 열어서 손으로 편집한다' 와 같은 식으로 해결하는 것이 보통이다. 물론 10 종 정도의 단백질이 들어 있는 파일이라면 이것이 가장 빠른 방법일지도 모르겠다. 수정할 라인이 100줄 정도 있다면 좀 시간이 걸리지만 어떻게든 할 것이다. 그렇지만, 1000줄, 10000줄, 100000줄을 수정해야 하는 경우라면? 아니면 이런 작업을 늘상 하는 경우라면?

'석사 1학기생 내지는 학부생 내지는 신입사원에게 시킨다' (-.-;;) 와 같은 방법 말고 좀 좋은 방법은 없을까? 그렇다고 이런  짜잘한 작업을 위해서 전문 프로그래머에게 프로그램을 짜달라고 하는 것도 좀 안습이다. SED 를 이용하면 명령어 한 줄로 이런 것을 해결할 수 있다.

리눅스 혹은 OS X를 사용하고 있는 사람이라면, 위의 예제 sequence.fasta 파일을 다운로드 받은 다음 터미널에서 다음과 같은 명령어를 입력해보자. (물론 sequence.fasta가 위치한 디렉토리 내에서)

cat  sequences.fasta | sed -E 's/^>gi\|[0-9]+\|ref\|[0-9a-zA-Z_\.]+\| (.*)\[(.*)\]/>\2/' | sed -E 's/ /_/g' >seq2.fasta


위 명령을 수행해서 생성된 결과 파일(seq2.fasta)을 열어보면 다음과 같이 각 단백질의 제목이 원하는 대로 바뀌었음을 알 수 있다.



위의 명령어는 처음 보는 사람은 거의 난수표(?) 로 보일지도 모르겠지만, 다음과 같은 기능을 수행하는 명령어이다.

1. cat 명령어로 sequences.fasta 파일을 출력
2. 출력된 결과를 한줄씩 SED로 보낸다.
3. SED에서는 FASTA 파일의 헤더, 즉 ">gi|15679284|ref|NP_2764....thermautotrophicus str. Delta H]" 와 같은 형식의 패턴을 검사하여 "[Methanothermobacter thermautotrophicus str. Delta H]" 와 같이 대괄호 내의 생물종 이름만을 추출하여 출력하고
4. 출력된 생물종 이름의 스페이스를 underscore로 바꾸어 변환한다.(이는 개인적으로 사용하는 Alignment Viewer인 Jalview에서 공백을 제대로 처리하지 못하기 때문에 궁여지책으로 넣은 것이다)
5. 결과를 redirection을 이용하여 seq2.fasta라는 파일에 저장한다.

이제 sed 를 이용하는 부분을 좀 더 자세히 뜯어보도록 하자.

sed -E 's/^>gi\|[0-9]+\|ref\|[0-9a-zA-Z_\.]+\| (.*)\[(.*)\]/>\2/'


라는 문장은

>gi|15679284|ref|NP_276401.1|aspartyl/glutamyl-tRNA amidotransferase subunit B [Methanothermobacterthermautotrophicus str. Delta H]

와 같은 패턴을 매칭하는 정규식 (Regular Expression)이다. 위의 정규식이 예로 든 패턴과 어떻게 매칭되는지는 아래를 참조.



추가 설명.

* -E : 확장 정규식 (Extended Regular Expression) 을 사용할 수 있게 하는 옵션이다. 확장 정규식을 사용하더라도 SED에서 사용할 수 있는 정규식은 Perl 정규식에 비해서 제약이 많다. 즉, Perl 에서 지원하는 \d+ 와 같은 메타 캐릭터를 지원하지 않으므로 [0-9]+ 와 같은 방식으로 써야한다.

* 괄호를 사용하여 캡춰한 영역은 \1, \2 와 같은 방식으로 억세스할 수 있다. 위의 예에서는 대괄호 내의 영역 (위의 예에서는 "Methanothermobacterthermautotrophicus str. Delta H") 는 위 정규식에서 두번째 괄호이므로 \2로 억세스할 수 있다.

* 단백질 이름 (aspartyl/glutamyl-tRNA amidotransferase subunit B 어쩌구 하는 부분) 역시 괄호로 캡춰되었으므로 \1로 억세스할 수 있다. 다음과 같이 명령어를 약간 바꾸면,


cat  sequences.fasta | sed -E 's/^>gi\|[0-9]+\|ref\|[0-9a-zA-Z_\.]+\| (.*)\[(.*)\]/>\1:\2/' | sed -E 's/ /_/g' >seq2.fasta


이번에는 이런 결과가 나온다.


즉, 첫번째 괄호 (.*) 로 캡춰한 단백질 이름은 \1에, 대괄호 안의 (.*)로 캡춰한 생물 이름은 \2 에 저장되어 있으므로 '단백질 이름:생물 이름' 과 같은 방식으로 포맷을 바꾼 셈이다.


이와 같이 SED는 매우 긴 텍스트 형식의 데이터 파일에서 일부만을 수정하고 싶을 때 매우 유용하다. 물론 파일 자체가 하나이고 vi 에디터 등의 치환 기능에 익숙하다면 그냥 vi 에서 불러 치환 기능으로 수정할 수도 있겠지만, sed 를 이용하여 쉘 스크립트를 만들어 두면 동시에 여러개의 파일에 명령을 적용할 수 있으므로 매우 편리하다. 물론 조금 더 복잡한 파싱 작업이라면 차라리 perl 로 스크립트를 작성하는 편이 낫겠지만, 위의 예와 같은 간단한 치환 기능을 반복적으로 수행해야 할 때는 SED는 매우 편리한 툴이니 잘 익혀두기 바란다.

by Newbie | 2008/01/23 12:38 | Bioinformatics/comp. | 트랙백(1) | 핑백(1) | 덧글(2)

트랙백 주소 : http://medialab.egloos.com/tb/1702372
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from gwLee's Lect.. at 2008/07/22 18:27

제목 : SED command
SED 는 유닉스 계열 운영체제 (Linux, OSX, Solaris 등등) 라면 기본적으로 어디에나 있는 기본 유틸리티로써, 정규표현식을 이용하여 간편하게 패턴을 검색하고 이를 이용하여 파일을 수정하는데 매우 유용한 유틸리티이다. 물론 펄이나 파이썬으로 스크립트를 짜서 할 수도 있지만, 치환문 하나로 끝나는 단순한 일이라면.... Media Lab에서... ex) sed 's/검색 패턴/치환될 문자열/' echo $M | sed -e "s/검......more

Linked at Media Lab : grep at 2008/11/14 17:24

... e [Acidovorax sp. JS42] ... 위 결과에서 refseq number (YP_984342.1 식으로 나가는 것) 과 유전자 이름만 뽑아내기. sed에 대해서는 이미 여기서 설명한 바 있다 grep "^>gi" NC_008782.faa | sed -E 's/^>gi\|[0-9]+\|ref\|([0-9a-zA-Z_\.]+)\| (.*) ... more

Commented by 폭주무면허 at 2008/01/23 18:05
펄 tr 과 같지만 조금 다른 것 같네요

어렵지만 왠지 곧 쓰게 될듯 합니다.
Commented by codebook at 2008/01/29 16:58
sed라는 명령어가 있는지 몰랐는데, 상당히 자세하게 설명해 주셨네요. 어째든 vi로 열수 없는 파일에 적용하면 좋을듯 하네요.

조금 딴지를 걸자면, 위에서 프로그램 짜기도 뭐한거 한줄에 처리가 가능하다라는 부분에서 보통은 그걸 한줄로 인식못한답니다. ^^

정규식이 뭔지는 알아도 능숙하게 잘 써먹는 사람은 얼마 안되듯이요.

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶