Media Log

/ 를 통해 쉽고 빠르게 원하는 문자열을 하이라이트 서치 할 수 있는 것만 해도 vim은 로그뷰어로서 꽤 쓸만하다.

많은 내용의 로그 파일을 읽을 때는 하이라이트 서치 외에도 보고 싶은 로그만 남도록 불필요한 부분들을 잘 쳐내는 것이 도움이 된다.

1. 특정 패턴이 존재하는 라인을 삭제
2. 특정 패턴이 존재하지 않는 라인을 삭제

불필요한 라인들을 쳐내기 위해서 위의 두가지 기능을 잘 이용할 수 있어야 한다.
물론 빔에서는 이것들을 아주 쉽게 해낼 수 있다.

그 내용을 설명하기 전에 먼저 패턴을 치환하는 방법을 살펴보자.

:%s/pattern/replace/g

위 명령어는 원하는 pattern을 replace로 전역 치환한다. 간단한 패턴이라면 머리 속에 잘 정리해서 한번에 위처럼 명령을 수행할 수 있겠지만, 조금 복잡하다면 먼저 패턴이 잘 매치되는지 부터 확인해보아야 할 것이다.
원하는대로 잘 매치가 되고 나면 이제 위에서 보이는 pattern 부분은 생략이 가능한데, 다음처럼 써서 이미 이전에 매치된 패턴을 치환시킬 수 있다.

:%s//replace/g
pattern 부분에 아무 것도 적지 않은 것을 주목해서 봐야한다. 빔은 저렇게 빈 패턴이 들어왔을 때 이전에 / 을 통해 마지막으로 매치시켰던 패턴을 기억하고 그 패턴을 대입해준다.

이제 처음 설명하기로 했던 2가지 기능을 알아보자.

특정 패턴이 존재하는 라인을 삭제
:g/pattern/d
위와 같은 간단한 입력을 통해서 특정 패턴이 존재하는 라인들을 삭제할 수 있다.
물론 위에서 설명한 것처럼 먼저 원하는 패턴을 한번 매치시켜놓고,
:g//d
라고 쓰는 것이 더 편리하다.
:g/pattern/p
위 명령은 특정 패턴이 존재하는 라인들만을 출력해준다.

특정 패턴이 존재하지 않는 라인을 삭제
위와는 반대로 특정 패턴이 존재하는 라인만을 남겨놓고 싶은 경우도 많이 생긴다.
:v/pattern/d
물론
:v//d
역시 가능하다.

v는 invert를 의미하며, 즉 :v//d는 선택되지 않은 패턴들을 삭제하겠다는 명령이 된다.

이 기능들을 얼마나 잘 사용하느냐는 정규표현식의 능숙도에 달려있다. 원하거나 원하지 않은 라인을 쳐내기 위해 해당 데이터를 잘 분석하고 정규식으로 매칭 시킬 수 있는 능력은 따로 연습해야 한다.
정규 표현식에 대해서는 따로 설명하지 않겠지만, 세상에서 가장 잘 쓰여진 정규식 책을 한 권 소개해 줄 수는 있다.


이 책은 이제는 아쉽게도 절판되었는데, 몇몇 사람들이 블로그를 통해 이 책을 팔아달라고 요청했지만 너무 아끼는 책이라서 나는 도저히 팔 수가 없었다.

빔 위키에 가면 유용하고 재미있는 팁들을 많이 배울 수 있다.
아래 처럼 vimrc에 적어주게 되면 F3 키를 한번 누름으로서 이전에 매치된 문자열이 포함된 라인들만 모아서 새창으로 자동으로 복사해준다.

nmap <F3> :redir @a<CR>:g//<CR>:redir END<CR>:new<CR>:put! a<CR><CR>

지금 설명한 것들과 그 외의 많은 기법들을 neocoin 님에게 배울 수 있었다.
KLDP에서 vim에 대해 질문을 하면 항상 그가 답해주곤 했는데, 많은 것들을 가르쳐주어서 너무나 고맙게 생각한다.
그의 위키에는 vim에 대한 많은 재밌는 이야기들이 있으니 관심이 있다면 한번씩 읽어보길 추천한다.

관련글


신고
  1. Favicon of http://sunyzero.tistory.com BlogIcon 김선영 at 2010.07.10 04:08 신고 [edit/del]

    "v는 Vertical을 의미하는데 나는 왜 이렇게 이름 지었는지를 깨달을 수가 없어서 그냥 '반대' 라고 해석하고는 한다."
    -> UNIX계열에서 v는 verbose나 혹은 invert로 사용됩니다.(대문자는 주로 version으로) 따라서 vim에서는 invert로 사용되었다고 생각되네요. vertical은 생소한데...아마도 아닌듯 합니다.

    참고로 grep도 -v 옵션이 invert의 의미로 사용됩니다.

    Reply
  2. Favicon of http://www.petabytes.org BlogIcon 김재호 at 2010.07.10 17:52 신고 [edit/del]

    엇. 제가 착각했었네요. :vs로 창을 수직으로 나눌 때랑 완전히 햇갈렸나봅니다. 도움말에는 vglobal로 되어있는데 invert가 맞는 것 같네요.

    Reply

submit

C++을 사용하다 보면 다른 언어의 라이브러리들이 부러운 경우가 많이 있다.

정규표현식은 그 중 하나였는데, 다행히도 VS2008 SP1 이상을 쓰고 있다면 TR1이 내장되어 있어 다른 어떤 써드파티 라이브러리를 연결하지 않고도 #include <regex> 한 줄만 추가해줌으로써 쉽게 사용할 수 있게 되었다.

다음은 원하는 문자열을 매치해서 결과를 받아보는 간단한 예제이다.
const std::string s("Hello World");

std::tr1::smatch m;
std::tr1::regex rx("(\\w+) (\\w+)");
bool fMatched = std::tr1::regex_match( s, m, rx );

if ( fMatched )
{
    std::cout << "size : " << m.size() << std::endl <<
                    "match0 : " << m[0] << std::endl << 
                    "match1 : " << m[1] << std::endl << 
                    "match2 : " << m[2] << std::endl;
}

size : 3
match0 : Hello World
match1 : Hello
match2 : World

match 객체의 첫번째 요소에는 매치된 모든 문자열이 담기게 되고, 그 다음 요소들 부터는 캡쳐한(괄호로 둘러싼) 문자열들이 저장된다. 위 예제에서는 첫번째 단어와 두번째 단어를 캡쳐해봤다. -물론 캡쳐 없는 괄호 (?: )을 사용해서 캡쳐 기능을 제거할 수도 있다.
파이썬이나 C# 등의 다른 정규식 라이브러리에서도 대부분 위와 흡사한 인터페이스를 제공한다.

다음 코드는 문자열을 치환한다.
const std::string s("Hello World");
std::tr1::regex rx("^\\w+");
std::string t = std::tr1::regex_replace( s, rx, std::string("Great") );
std::cout << t << std::endl;

위 코드는 첫 번째 단어를 "Great" 라는 문자열로 치환시킨다.
Great World


치환할 때 백레퍼런스도 역시 사용이 가능하다.
std::tr1::regex rx("(^\\w+)");
std::string t = std::tr1::regex_replace( s, rx, std::string("Great $1") );

첫번째 캡쳐그룹을 치환시에 재사용 하였다.
Great Hello World


간단하게 설명하기 위해서 예제의 실용 가치가 없어져 버렸지만, 잘 응용하면 많은 곳에 적용할 수 있을 것이다.

예전에 이메일 검증 함수를 골뱅이와 .을 찾아가면서 CString의 Find 함수로 떡칠을 하면서 만든적이 있었는데, 시간이 지나고 어느 날 RFC 문서에서 이메일 형식 명세를 보다가 아 내가 엉터리로 만들었구나 하고 깨달았던 기억이 난다. Email이나 URL 형식 같은 것들은 정규식 없이 검증 함수를 만들기엔 생각보다 훨씬 복잡하다.

다른 언어들보다 사용법이 조금 까다롭고 보기에도 좋지는 않지만, 이 정도만으로도 C++ 프로그래머들은 고마움에 눈물이 날만하다.

C++0x에서는 파이썬의 r""이나 C#의 @"" 같은 raw string 기능도 언어에 포함될 예정인데, 그 때가 되면 조금 더 보기 좋게 정규식을 사용할 수 있을 것이다.

신고
  1. Favicon of http://kate.textcube.com BlogIcon Briller_Kate at 2009.07.02 00:55 신고 [edit/del]

    태정님 블로그에서 주로 볼 수 있었던 @_ @ 포스트! ^^;

    Reply
  2. 이종협 at 2011.04.14 15:32 신고 [edit/del]

    제법인데 ㅋㅋㅋ regex 때문에 골머리 아퍼~
    AutoCad 쉐리들은 왜케 프로그램을 잘만들어서 귀찮게 하는지..

    Reply

submit
정규 표현식 완전 해부와 실습 - 10점
제프리 프리들 지음, 서환수 옮김/한빛미디어

최근 한 달여 동안 침대에서 이 책과 함께 잠이들곤 했다.

이 책은 정규표현식을 다루는 최고의 명서이다.

인터넷을 둘러보다 보면 정규 표현식을 설명하는 많은 문서들에서 언제나 빠짐없이 등장하는 단 한권의 책이다.
-거의 모든 문서들에서 많은 정규식 책들 중 오직 이 책만을 추천하고 있을 정도로 이 책의 위상은 독보적이다.

이 책은 3판(2006)까지 나와있는데, 우리말로 되어있는 것은 2판(2002)이다.
이 책의 저자는 정규 표현식 분야의 권위자이며, 실제로 정규 표현식의 발전에 많은 기여를 했다.

다음은 이 책(2판)의 목차이다. -3판에는 PHP가 추가되어있다.

1장. 정규 표현식 소개
2장. 기초 예제
3장. 정규 표현식의 기능과 종류
4장. 정규 표현식 처리 원리
5장. 실용 정규 표현식 기법
6장. 효율적인 정규 표현식 사용
7장. 펄
8장. 자바
9장. 닷넷

정규식을 처음 접하는 사람이 이 책의 1장과 2장을 보고 나면,
"이제 나는 정규 표현식의 달인이야. 이제 이 책은 더 이상 안봐도 되겠어. 나머지는 실전으로 익히자." 라는 욕망에 사로잡히게 될지도 모른다.
나는 실제로 그랬는데, 아마 저자는 이미 그런 마음을 잘 알고 있었나보다.
부디 책을 끝까지 정독하라는 충고를 곳곳에서 해주지 않았더라면 나는 분명히 이 책을 다 읽지 않았을 것이다.

그럼 이렇게 배워둔 정규 표현식을 어디에 써먹을 것인가?

정규식을 써야하는 곳은 수도 없이 많다. 아는만큼 보인다는 말이있다.
심지어 이 책의 저자는 책의 오류를 찾기 위해 정규식을 사용하기도 했는데, 이것은 정규식을 모르는 사람들은 상상도 할 수 없는 기발한 생각이다.

이런 유틸리티 목적만으로도 우리의 삶을 충분히 편하게 해주지만,
우리는 프로그램에서도 멋진 식들을 활용해보길 원한다.

프로그래밍 코드에서 정규식을 사용해야하는 가장 잦은 부분, 그리고 중요한 부분은 아마도 입력값 검증일 것이다.

Writing Secure Code에서 마이클 하워드는 입력값 검증의 중요성을 무던히도 강조하는데,
그는 항상 모든 입력값을 정규식으로 완벽하게 체크하는 좋은 습관을 보여주었다.

이 책에서 저자는 정규식을 테스트 하기위해 perl 과 egrep을 많이 사용하는데,
내가 좋아하는 툴은 바로 vim이다.

나는 그동안 vim에서 정규식으로 매치를 해보고 치환을 할 때, 매치했던 표현식을 다시 재사용하는 방법을 몰라서 다시 힘들게 타이핑 하곤했는데 오늘 KLDP에서 좋은 답변을 얻었다.

vim에서 정규식으로 문자열을 치환하기 위해

/^some[regular]expression(.*)$ 와 같은 식을 만들어 먼저 원하는 문자열이 잘 매치되는지 확인을 해봅니다.

이제 :%s/the expression/replace string/g 를 통해 문자열을 바꾸고 싶은데,
위에서 썼던 식을 복사하고 붙여넣는 방법을 몰라서 다시 머리를 싸매며 타이핑하곤 합니다.

간단하게 할 수 있는 방법이 있습니까?


:%s//replace string/g


이 책은 번역이 아주 잘되어 있고 꽤나 신경을 써서 만들어진 흔적이 엿보인다.
단지 흠이 있다면, 몇몇 정규표현식에서의 오타와 예제 문자열들에서 있어야할 밑줄이 상당수 빠져있는 것인데, 내용을 이해하는데 있어서 그렇게 불편한 정도는 아니다.

이런 부분들의 교정과 함께 3판 또한 출간된다면 나는 아주 기쁠 것 같다.

신고
  1. at 2009.05.12 18:29 [edit/del]

    비밀댓글입니다

    Reply
  2. at 2009.12.22 04:46 [edit/del]

    비밀댓글입니다

    Reply

submit