2016년 7월 10일 일요일

VIM 사용 설명서 - 2nd

VIM 기능 중에서도 꽃 중의 꽃이라고 할 수 있는 문자열 치환 기능에 대해서 알아보자. 문자열 치환 명령어 역시 당연히 명령 모드에서 동작하며, 형식은 다음과 같다.


해당 명령어는 검사 대상 문자열에서 ②를 찾아서, ③으로 바꿔준다. 즉 명령어 ':%s/aaa/bbb/'를 입력하면 aaa 문자열을 찾아서 bbb로 바뀌주며, /로 구분되는 세 개의 영역은 다음과 같은 특징을 가지고 있다.


실제 사용 사례를 보자. 명령어 ':%s/z/ㅋ/'를 사용하면 알파벳 대소문자 Z와 z를 한글 자음 'ㅋ'으로 바꿔준다.

치환 전

치환 후

미리 대소문자를 구분하지 않도록 설정(:set ignorecase)을 해놨기 때문에 대문자 Z와 소문자 z가 모두 바뀌었다. :set ignorecase 설정을 하지 않았다면? 소문자 z만 바뀐다.

특징1

첫 번째 특징은 줄 단위로 최초 일치하는 문자만 바뀐다는 것. 무슨 뜻일까? 대문자 Z와 소문자 z가 각각 2개씩 존재하는 다음 검사 대상 문자열에서 같은 명령을 실행해보자.

치환 전

치환 후

대문자 Z와 소문자 z가 각각 2개씩 존재함에도 줄 단위로 일치하는 첫 번째 문자만 바뀐다는 사실을 알 수 있다. 만약 일치하는 모든 문자를 바꾸고 싶다면 g(lobal) 옵션을 사용하면 됨. 그런데 이게 뭐 대단한 기능이라고 구구절절이 소개하고 있을까?


데이터를 원본 상태 그대로 분석할 수 있다면 참 좋겠지만 그랬다면 데이터베이스나 빅데이터와 같은 기술은 나오지 않았을 것이다. 그리고 그런 기술들은 ETL(Extract, Transform, Load)이라 불리는 데이터 가공 과정을 거쳐야만 비로소 원시 로그 분석과 차별화된다.

그렇기 때문에 로그 분석이 아닌 데이터 분석을 하고 싶다면 ETL 과정을 거쳐서 원시 로그를 (유효한 데이터가 중복되지 않는 필드로 저장된) 테이블 구조로 만들어야 하는데, 이때 VIM의 문자열 치환 기능이 매우 유용하기 쓰인다.

백문이 불여일견이다.  헬로 데이터 과학 후기에서 잠깐 소개했던 secure 로그에 sshd 문자열 기준의 ETL 과정을 적용해보자.

'sshs' 문자 추출을 위해 구분기호(ㅋ) 추가

'데이터 > 텍스트 나누기' 메뉴에서 구분기호로 나주기

일치하는 첫 번째 문자열에만 구분기호(ㅋ)가 추가됐기 때문에 원했던 대로 sshd 문자열 기준으로 분리된 테이블 구조를 만들 수 있었다. 

그러나 g 옵션을 사용한 다음 결과를 보면 일치하는 모든 문자열에 구분기호가 추가되면서 줄 단위로 통일된 구분기호가 적용되지 않음을 알 수 있다. 일관된 기준의 테이블 구조를 만들지 못한 것.



같은 성격의 필드가 중복되면 데이터 중복이 발생하면서 통계 및 관계 분석 등 데이터 분석의 신뢰도는 떨어질 수 밖에 없다. 결론은 VIM 킹왕짱! (더 좋은 툴 있으면 제보 좀)

특징2

두 번째 특징은 바로 '③ 치환 후 문자열' 영역에는 정규표현식을 사용할 수 없다는 것. 사용할 수 없으면 사용 안 하면 되지 않나? 그런데 '치환 후 문자열' 영역에서 정규표현식을 사용하지 못하면 매우 난처한 상황이 발생할 수 있다.

나중에 기회가 되면 VIM 정규표현식(http://vimregex.com/)에 대해서도 다뤄볼까 하지만 일단 정규표현식에서 .은 마침표가 아니라 '임의의 모든 문자'를 의미하는 메타 문자임을 알아두자. 다음처럼 .을 검색어로 사용하면 모든 문자가 검색된다.



그런데 만약 검색어와 일치하는 문자 옆에 'ㅋ'을 추가(첫 번째 줄의 !를 '!ㅋ'으로)하고 싶다면 어떻게 해야 할까? 치환 명령어 ':%s/./.ㅋ/'로 가능할까?

다음 치환 결과를 보면 '치환 후 문자열' 영역은 정규표현식을 인식하지 않기 때문에 메타 문자 .을 마침표로 인식한 결과, 검색어와 최초 일치하는 문자를 유지하지 못하고 전부 '.ㅋ'으로 바꿔버렸다.


원본 데이터가 사라져버린 것. 그러나 실망하긴 이르다. 이럴 때 쓰라고 VIM은 '치환 전 문자열' 영역의 검색 결과를 기억해주는 &라는 메타 문자를 제공한다. 다음 치환 결과를 보자.


메타 문자 &가 '치환 전 문자열' 영역에 사용된 검색어의 결과를 기억해서 '치환 후 문자열' 영역에 반영해준 결과 원본 데이터를 그대로 유지하면서 문자 'ㅋ'이 추가된다는 사실을 알 수 있다. 너무 너무 유용한 기능이니 반드시 기억해두자.

특징3

특징을 하나만 더 알아보고 마무리할까 한다. 보통 문자열 치환 기능은 검사 대상 문자열에서 치환을 원하는 문자열을 검색해본 후, 검색 결과에 문제가 없으면 실행한다. 즉 선 검색, 후 치환이다.

그런데 검색 과정에서 검색어가 너무 길어지거나 복잡해지면 치환 시 '② 치환 전 문자열 영역'에 다시 검색어를 입력하는 과정이 고역이 되기 십상. VIM은 이런 문제를 너무나 간단하게 해결해준다.

다음은 줄 단위로 최초 세 개의 문자만을 검색한 후, 해당 문자열의 오른쪽에 'ㅋ'을 추가하는 과정.


사용된 문자열 치환 명령어를 보면 '치환 전 문자열 영역'에 검색어 '\v^.{3}'를 입력하지 않고 비워뒀음에도 의도했던 치환이 이루어졌다. 무슨 조화일까?


VIM이 기특하게도 검색 모드에서 마지막으로 사용된 검색어를 기억했다가, 명령 모드에 자동으로 반영해준 것. 문자열 데이터를 지지고 볶는 데는 정말 VIM이 킹왕짱!! 이런 과정을 통해 데이터의 의미를 찾게 되고, 그 과정이 정형화된다면? 상상만 해도 즐거워진다. 

관련 글

댓글 없음:

댓글 쓰기

크리에이티브 커먼즈 라이선스