Media Log


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