전화번호부

전화번호를 찾는 패턴을 살펴볼까요? :

* 응용 패턴 1: [0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]

 

이렇게 하면 다음 전화번호 같은 거 쉽게 찾습니다.

032-812-6333

헷갈리지 마세요. '-' 문자는 [] 안에서만 특별한 의미가 있습니다.

근데 지역번호가 항상 0으로 시작하더라... 따라서 123-812-6333 같은건 가짜더라...라고 판단이 되면...:

* 응용 패턴 2: 0[0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]

 

로 바꿔주면...

132-812-6333

이런건 가짜라서 안찾습니다. 쉽지요?

눈치 빠른 분들은 웹사이트 등에서 이메일이나 전화번호, 계좌번호 같은 일정한 틀이 있는 입력항목을 어떻게 확인하는지(validation) 아시겠지요? 대부분 regex를 씁니다. 주어진 regex 패턴을 통과하지 못하면 이메일 주소가 올바르지 않습니다 라는 오류 메시지가 나오는거지요:-)

HTML 소스에서 태그 날리기

이것도 쉽습니다. 아무 웹페이지나 가서 HTML 소스 하나 가져오세요. 그걸 울트라 에디터에서 보세요. 거기서 태그만 다 날리고 실제 웹에서 보는 문자들만 남기고 싶다... 어떻게 할까요?

regex 모르면 역시 맨땅에 헤딩입니다. 게다가 손으로 하면 실수하기 쉽구요. 이렇게 하면 끝납니다:

* 응용 패턴1: <.*> => 공백

 

<html>, </html> 식의 태그만 쏙쏙 뽑아 몽땅 날려줍니다. < 로 시작하고 중간에 어떤 문자(.)가 몇번 반복되건(*) 상관없고 끝나는것만 > 로 끝나면 된다...니까요.

근데 문제가 있습니다. . 패턴은 줄바꿈 문자는 찾지 않거든요. 그래서 태그가 길어져 다음 줄로 넘어간건 못찾습니다:

<table border="0" >

 

식의 태그 말입니다. regex는 art라고 했습니다. 마술을 부려 봅시다:

* 응용 패턴2: <[^<>]*>

 

쬐끔 복잡하지요? 근데 역시 < 로 시작해 > 로 끝나는 문자의 연속이라는 패턴은 같습니다. [^<>] 가 헷갈릴 지 모르지만 어떤 문자라도, 심지어 줄바꿈 등 특수문자가 계속되도 상관없지만 단, < 라는 문자와 > 라는 문자만 없으면 된다는 의미거든요.

그러니 줄바꿈이 들어가 잘려진 태그도 찾아내서 날려보내 줍니다. 예술이지요?

진짜 실험해 보세요. 아무리 복잡한 HTML 소스라도 깔끔히 정리해줍니다.

이메일 주소만 찾기

쬐끔 어려운 거 해보고 끝내겠습니다. 더 지겨워들 하기전에 :-)

이메일 추출기 원리입니다. 아니 사실 나쁜데 쓰지 않으면 거의 중급 수준의 regex로 이정도면 여러분 웬만한 문서 작업에서는 남들보다 날라다닐 수 있을 겁니다:

* 응용 패턴 1: [\_\.\-a-z0-9]+@[\_\.\-a-z0-9]+

 

이메일만 잡아냅니다. @ 를 좌우로 해서 _ 나 -, . (이스케이프를 시켜줘야 regex에서 쓰는 특별한 의미가 아닌 문자 그대로의 의미로 받아들임) + 문자나 숫자로 반복되는 문자열을 양쪽으로 잡아내는 겁니다.

지금 해보세요. 이 문서에도 이메일이 몇개 있습니다. 그거 다 잡습니다. 쬐끔 응용을 하면...:

* 응용 패턴 2: ([\_\.\-a-z0-9]+)@([\_\.\-a-z0-9]+)

 

골뱅이 양쪽 문자열을 괄호로 감싸줬지요? 이걸 바꾸기에 응용하는 겁니다. 모든 이메일 주소를 spam 에 악용되지 않게 wankyuchoi@gmail.com 이라는 건 wankyuchoi at gmail.com 식으로 사람이 읽듯 바꿔줘 버리는 겁니다.

겁나게 쉽습니다:

* 바꾸기 패턴: \1 at \2

 

\1 은 첫번째 괄호 결과값 \2 는 두번째 괄호 결과값이라고 했지요? (이런식 표현은 9개까지 가능합니다. 1,2,3,4,5,6,7,8,9... 괄호를 아홉개까지 써서 바꾸기에 응용한다는 거지요. 9개까지 쓸 수 있으면 여러분도 regex 아띠스뜨~ 입니다.)

한번 해보세요. 응용 패턴 2를 찾기 상자에 넣고 바꾸기 패턴을 바꾸기 상자에 넣고 몽땅 바꾸기 말고 하나씩... 그럼 어떻게 바뀌는지 보일겁니다.

예를 들어 게시판에 있는 모든 글속의 이메일 주소를 이런식으로 바꾸라고 윗사람이 생 난리를 친다... 그 사람 regex 라는 거 모른다... 그럼 한 한달 걸리는 걸로 안다... 그럼 한 10초 해서 바꿀 거 생각하고 1달 휴가 갔다 오면 된단 말입니다. 글고 나서, "부장님 저 엄청 뺑이쳤어요... 글이 좀 많아야지요..." 해 보세요.

그럼 "진짜 수고했어..." 그럴겁니다. :-)

그럼 http://www.google.com 이나 ftp://ftp.google.com 식은? :

* 응용 패턴 3: [a-z]+://[^ ]+

 

역시 쉽지요? 알파벳 문자열의 연속(http, ftp) + :// + 공백이아닌([^ ]) 문자열의 연속(+) :

* 응용 패턴4: http(://[^ ]+)

 

http:// 를 ftp:// 로 바꾸고 싶다... 바꾸기에서 ftp\1 이렇게 해주면 되겠지요?

역시 눈치 빠른 분들은 뭔가 번뜩이는게 있을 겁니다. HTML anchor 태그도 쓰지 않았는데 게시판 같은 프로그램을 보면 간단히 URL만 적어도 링크를 자동으로 걸어주지요? 웬만한 게시판들에는 이 기능이 있습니다. 어떻게 하는 걸까요? 예, regex 입니다.

그만 쓸랍니다. 더 나가면 저나 여러분 모두 돌아버릴 것 같아서... :-)

컴퓨터의 노예가 되지 말자

우리 모두 알고 살았으면 합니다. 모르면 수족이 고생이라는 게 맞는 말이더라구요. 정말 주변에 그런 일 많이 봤습니다. 몇년전에 어쩌다 친구 사무실 놀러갔는데 그 놈이 글쎄 한달동안 문서 작업했다고 뭔가 보여주더군요. 몇백 페이지짜리 문서를 공백만 딜리트키 엄청 누르면서 줄맞추고...

눈물이 앞을 가렸습니다. 안타까움에 부둥켜 안고 펑펑 울고 싶었습니다. 한달... 아깝지 않아요? 부모님 묘를 찾지 못해 묘앞의 팻말을 몽땅 뽑아와서 낭패를 본 까망눈 아저씨를 보고 눈물을 흘리던 윤봉길의 마음이었습니다. 윤봉길 의사가 독립운동을 시작한 이유라고 하지요.

그러지 말자구요.

한가지는 명심하자구요. 컴퓨터 만든 놈들은 알게 모르게 귀찮은 거, 단순 반복 겁나게 싫어하는 놈들입니다. 그래서 단순반복 맨땅 헤딩 이런거 안하려고 무지 많은 걸 만들어 놨습니다.

뭔가 이건 인간이 할 짓이 아닌 거 같은데... 로보트 없나? 라는 생각이 드는 무식한 작업이 있으면... 분명 딴 방법이 있습니다.

여러분이 다음에 해당한다면 다시 생각하고 조금만 배워서 활용하고, 그 낭비할 시간에 휴가 가서 재충전하고 옵시다.

  • del 키나 backspace 를 1분 이상 반복적으로 눌러댄 적이 있다.
  • abc 순으로 줄을 정렬하느라 대가리 뽀개진 적이 있다. ( 실제로 이런 사람 많습니다. 정렬이 뭔지 몰라서... )
  • 한 문서에서 하던 일을 또 다른 문서에서 똑같이 하며 "에이, !@$!@#!@$#@$... 이런 단순 무식한 일을 시키고 #$#@$ 이야..." 라고 푸념한 적이 있다.

끝으로.. 걍... 아무도 관심 없으실 수도 있지만... 쩌기 regex에 덧붙여 쬐끔만 프로그래밍, 아니 스크립팅을 배우면 regex로 벌 수 있는 정신적 육체적 시간 X 100 배의 효과를 낼 수 있습니다.

프로그램 아무나 하나...

예, 아무나 합니다. 딴 놈들도 다 그렇게 아무나 하는 줄 알고 시작한 거구, 저도 그랬구요. 앞에 말한 100배 라는 시간... 사실 그런 기초적인 것까지는 1주일이면 배우거든요.

여러분... 컴터의 노예가 되지 말고 부려 먹읍시다.

여러분은 일을 시키는 입장이어야 합니다. 일은 컴터가 해야 하구요. del 키 열라 누르는건... 일은 여러분이 하고 컴퓨터는 노는 겁니다.

명령 하나 때리고 커피 마실때 컴퓨터 혼자 땀 삐질삐질 흘리며 뭔가 일할때... 비로소 여러분은 그 컴퓨터의 master이고 컴퓨터는 slave가 되는 겁니다.

기계의 노예가 되지 맙시다.

우리나라에서 컴퓨터를 소지한 여러분들이 이정도만 아신다고 해도... 우리나라 경쟁력은 하늘을 찌르지 않을까... 또라이같은 생각도 해봅니다.

Regex 에 대해 더 배우고 싶으신 분이 계시면 다음 책 사서 읽어보세요. 단, 번역서 사지 마세요^^ 이유는 짐작하실겁니다.

아마존에 있고 우리나라 컴퓨터 원서 파는 대부분 대형 서점에 있습니다.

더 이상의 regex 책은 없다고 해도 과언이 아닙니다.

 

Mastering Regular Expressions by Jefferey E.F. Friedl - O'Reilly and Associates, Inc.


 

Regex 예제 둘 - 단어장

단어장 만들기 예제를 해보지요. 일단 좀 무식하게 공부하는 사람이 연설문에서 a로 시작하는 단어만 뽑아내겠다고 생각했다고 칩시다:

* 응용 패턴 1: [ \t]a[a-z]+

 

첫번째 '[ \t]a'의 의미는 '공백문자+a'로 시작하는 단어의 뜻이겠지요? 그래야 단어 중간에 있는 a랑 일치하지 않을테니까요. 그다음 [a-z]+ 의 의미는 a로 시작해서 어떤 문자든지(숫자나 공백말고) + 만큼(1번이상) 반복되는 경우를 찾으라는 겁니다.

이렇게 하면 a 는 찾지 않겠지요. +one or more의 뜻이니까요. 근데 짜증나게도 an, as같은 짧은 단어도 찾습니다. 그 정도 단어들은 너무 쉽다.. 최소한 3개는 되야...:

* 응용 패턴 2: [ \t]a[a-z][a-z]+'

 

이렇게 해주면 가운데 [a-z] 가 들어가니 3자리 문자만 나오겠지요. 아참, 대소문자 구분도 해주려면 [a-zA-Z] 가 되어야 한다는 거 잊지 말구요. 아니면 찾고 바꾸기에서 대소문자 체크를 꺼주던가.

근데 문제가 있지요?

"에이... 찾긴 했는데 일일이 뽑아내라구?"

그럴려면 regex 안쓰겠지요. 그럼 a 로 시작하는 단어 단어장 만드는 regex를 순서대로 실험해 보겠습니다. [네오퀘스트 특강 - 클린턴 연설문] 에 다음 regex를 순서대로 적용해 보는 걸로 합니다:

* 응용 패턴 3: [ \t][^a]* => ^p

* 응용 패턴 4: ^[^a]* => ^p

* 응용 패턴 5: [^a-z] => ^p

* 응용 패턴 6: ^[^a]*$ => ^p

* 응용 패턴 7: ^..$ => ^p

* 응용 패턴 8: \r\n\r\n => \r\n

 

사실 유닉스라면 좀더 융통성이 있는데 울트라 에디터는 제한적인 regex만 가능해 단계가 쓸데없이 좀 많습니다.

패턴 3은 a 로 시작하지 않는 단어를 몽땅 찾아냅니다. => ^p 라는 말은 바꾸기 상자에 ^p 를 넣어서 찾은 말을 모두 줄바꿈 표시로 (바꾸기 상자에서 ^p 는 울트라 에디터에서 줄바꿈 기호를 뜻합니다. 그럼 줄줄이 붙여줍니다.) 바꿔주라는 말입니다.

그냥 바꿔주면 다닥다닥 단어들이 붙어버리니까요.

패턴 4는 이렇게 바꾼 문서에 다시 a로 시작하지 않는 단어를 걸러내는 역할을 합니다. 처음 '^'는 줄의 시작을 뜻하며 [^a]* 는 a로 시작하지 않는 문자의 연속(*는 zero or more)을 뜻하니까요.

패턴 5에서 쉼표나 뭐 이런게 줄바꿈으로 바뀝니다. [^a-z]문자가 아닌 건 몽땅이라는 뜻이니까요. 그래서 a-non 식의 문자는 a 줄바꿈 non이 되지요. 그래서 다시 a로 시작하지 않는 문자를 바꿔줘야 합니다.

그게 패턴 6입니다. ^ 줄의 시작 + [^a]* a 로 시작하지 않는 단어의 연속 + $ 니까 줄의 끝이지요? 이걸 다시 ^p 로 바꿔주는 겁니다.

패턴 7은 선택입니다. '.'은 문자 하나를 뜻합니다. 어떤 문자든 상관없습니다. ^.$ 라고 하면 달랑 한줄에 문자 하나 있는 단어를 뜻합니다:

a A

 

이런거지요. 이걸 몽땅 다시 줄바꿈을 하는 겁니다. 두자리 문자도 싫고 세자리도 싫으면 '^..$', '^...$', 자리수만큼 . 을 사이에 넣어주면 됩니다:

aa aaa ab abc an

 

식의 단어가 모두 사라집니다. 마지막으로 줄바꿈이 엄청 많지요? 유닉스에서는 달랑 줄바꿈문자만 있는 줄을 날려버리는 이디엄이 있습니다. ^$ 라는 건데요. 줄의 시작을 알리는문자 바로 뒤에 줄의 끝을 알리는 문자가 오는 줄... 다시 말해 달랑 엔터만 친 줄을 뜻합니다. 이걸 몽땅 공백으로 바꿔주면 다 날라갑니다.

안타깝게도 울트라 에디터는 이걸 지원못합니다. 따라서 \r\n\r\n (윈도우니까) 식으로 다닥다닥 두줄이 연속해 붙어있는 걸 찾은 횟수 0이 나올때까지 서너번 돌려줘야 합니다.

마지막으로 파일 메뉴 np_icon_right_arrow.gif 정렬 메뉴np_icon_right_arrow.gif 파일 정렬메뉴 에서 순서대로 정렬을 해주면... 예 a 로 시작하는 단어장이 완성됩니다.

또 한번 느끼셔야 합니다. 사실 이거 설명만 길지 실제로 해보면 (손에 익으면) 10초도 안걸립니다. 수백 페이지건, 수천 페이지건, 아니 수만 페이지짜리 문서가 수천개가 널려 있건 상관이 없습니다. 울트라 에디터에서는 파일내에서 찾고 바꾸기도 지원을 하기 때문에 특정 디렉토리 아래, 또 그 하위 디렉토리까지 몽땅 파일을 찾아서 패턴을 바꿀 수도 있거든요. 이론상으로는 이 세상의 모든 문서에서 단어를 뽑아내는 일을 컴퓨터에게 시키고 여러분은 휴가를 다녀올 수도 있다는 겁니다 :-)

Regular Expression을 알고 쓰는 여러분은 이미 경쟁력이 남들보다 10년은 앞서갑니다. 아니 여기에 스크립팅 쬐끔 배우면 여러분만의 무슨 영어 문서든 단어장을 10초에 맹그는 도구를 갖게 될 수도 있습니다.

b 로 시작하는 단어장... 쉽겠지요? :

* 응용 패턴 9: [ \t][^ab]* => ^p

 

이렇게 a랑 b 를 함께 찾을 수도 있습니다. a 단어장이랑 b 단어장이 좀 적다 싶으면 앞에 나온 패턴들에 a 부분을 ab로 바꿔주면 되는거지요.

좀 어려웠나요? 그럼 쉬운거 몇개 해보고 비법 전수를 끝내도록 하지요 :-)


Regex 예제 하나


그럼 간단한 예제 하나 해보면서 regex의 맛을 보겠습니다. 도입부에 언급했던 긴~~~ 문서에서 연도를 찾는 걸 해보지요. Regular Expression은 다른 말로 pattern matching이라고도 합니다. 문자속에서 일정한 패턴을 찾는다는 겁니다.

따라서, regex를 쓸때는 어떤 패턴에 적용할지 이 패턴을 머리속에 정의해보는게 중요합니다. 그리고 찾고 바꾸기를 하기전에 반드시 찾기를 먼저 해봐서 내가 생각하는 패턴만을 찾는지 확인해야 합니다. 그래야 엉뚱한 결과를 막을 수 있거든요. 컴퓨터의 모든 부분이 마찬가지지만, regex 역시 면도날과 같아서 좋은 도구가 될 수도 있지만 베일 수도 있다는 뜻입니다.

울트라 에디터 9.0부터는 찾고 바꾸기를 한 것에 대해서도 undo가 가능하니 좀 낫지만 이전 버전에서는 엉뚱하게 바꾸고 나면 정말 하늘이 무너지는 결과를 낳기도 했습니다. 조심 또 조심... 언제나 원본을 백업해 두는 것도 잊지 마세요. 언제나 빠꾸가 가능하도록... :-)

자 그럼 연도의 패턴을 봅시다. 일단 연도는 네자리수만 있지요. 물론 그 이전도 있지만 편의상 여기선 4자리만 따지겠습니다:

* 찾고자 하는 패턴: 1234, 1940, 1999, 2000, 2002 등등

* 정규 표현식: [0-9][0-9][0-9][0-9]

 

원래 유닉스라면 [0-9]{4} 식으로 4자리 반복가능을 직접 지정해 줄 수 있는데 울트라에디터에선 안됩니다. 저렇게 무식하게 해줘야 하지요.

일단 4문자를 찾는다는 건 '[]' 가 네번 반복되기 때문에 알 수 있습니다. '[]' 안에 0-9 가 있으니, 0,1,2,3,4,5,6,7,8,9 만 찾는다는 것도 알 수 있습니다. [0-9] 는 '[0123456789]' 와 의미가 같으니까요. 따라서 당연히 1234, 1940, 1999, 2000, 2002 식의 내자리 숫자만 찾습니다. 좀더 응용해서 "2천년대라는 건 안다..."싶으면 '2[0-9][0-9][0-9]'라고 해주면 되겠지요? 2천 10년대만 찾는다면? 201[0-9] 예술입니다 :-)

지금 실험해보세요. 울트라 에디터에서 CTRL+F 를 눌러 검색 창을 연 다음 (정규식 에 체크하고) 찾기 텍스트 상자에 2[0-9][0-9][0-9] 라고 입력하고 찾아보세요. 그럼 이 문서에 나온 2천년대 숫자만 찾을 겁니다.

Regex 는 Art 다

regex는 art다... 상상력을 동원해보세요. 이것만 가지고도 여러분은 별짓 다할 수 있습니다:

* 응용 패턴 1: 1[0-9][0-9]1 (1231, 1991 식의 연도만 찾기)

* 응용 패턴 2: 19[0-9][0-9] (1900 년대만 찾기)

 

참고로 [0-9]\d 로 대체가 가능하다고 했습니다. 2[0-9][0-9][0-9]2\d\d\d 와 같다는 말입니다.

그럼 바꾸기 해보까요? 지금은 2천년대라 의미가 없지만 20세기에는 80년대, 60년대 식의 표현을 썼습니다. 60은 1960, 80은 1980인거지요.

20세기에 만들어진 1만페이지짜리 문서에 모두 이렇게 돼 있는 겁니다. 이것도 Y2K 버그지요. 90년대 정치상황으로는.... 90년대와서는...

이 문서의 이런 시의성 떨어지는 표현들을 모두 1980년대, 1990년대로 바꾸고 싶으면 어떻게 찾으면 될까요? 쉽지요? :

* 시험 패턴 1: [0-9][0-9]년대

 

해보세요. 아주 잘찾습니다. 근데 너무 잘 찾아서... '1990년대'까지 찾습니다. 아무 생각없이 찾고 바꾸기 해버리면 191990년대 식의 표현도 등장할 수 있다는 겁니다. 그래서 찾기를 먼저해서 실험해 보라는 겁니다. :

* 시험 패턴 2: 공백[0-9][0-9]년대

 

공백은 공백을 표시하기 위한 겁니다. 찾기 창에 공백이라고 쓰라는 게 아니고...

앞에 공백을 하나 넣고 찾아보세요. 이제 1990년대 문제는 사라졌지요? 근데 공백이 아닌 \t 문자가 앞에 있는 '\t90년대'식의 표현은 찾지 못할 겁니다:

* 시험 패턴 3: [ \t][0-9][0-9]년대

 

이럼 다 찾습니다. [ \t] 의 의미는 공백 또는 탭 문자니까요. 이걸 더 쉽게 하려면 '\W[0-9][0-9]년대'라고 해주면 됩니다. 근대 안타깝게도 \W는 한글도 포함됩니다. 한글이 원래 컴퓨터에게는 이상한 특수코드로 입력이 되기 때문에... 그래서 조심하란 겁니다:

* 최종 찾기 패턴: [ \t]([0-9][0-9])년대

 

안전하게 한글을 다치지 않기 위해. 여기 나오는 괄호부분이 나중에 바꾸기에 활용을 하겠다는 뜻입니다.:

* 바꾸기 패턴: 19\1년대

 

\1 은 앞에 괄호로 감싼 부분 [0-9][0-9] 에서 찾은 결과값으로 대체하라는 뜻입니다. 90년대 를 찾았다면 90이 그 값이기때문에 1990년대 로 변환이 되지요.

한번 해보세요. 아니 해봐야 뭔소린지 압니다. 꼭 해보세요. regex의 빠워~를 한번 느껴보세요. 몽땅 바꾸기 하지 말고 하나씩 해보면서 어떻게 찾고 변하는지 보면... regex의 마술을 느낄 수 있을 겁니다. 아니 무한한 가능성... 아... 앞으로 수없는 뺑이를 줄일 수 있겠다는 안도감... 뭐 그런게 느껴지신다면 이 길고 긴 난수표같은 제 글도 더 이상 멍멍 np_icon_dog.gif 만은 아니겠지요 :-)

두번째 예제로 이어집니다.



정규 표현식의 기본

앞에서 잠깐 언급했지만 한대가리 한다는 사람들도 regex(앞으로 정규표현식 다 regex 라고 하겠습니다)를 접하면 "오 신이시여..." 를 연발하게 됩니다. 도대체가 예술이라고밖에 생각할 수 없는, 인간의 머리로 만들어냈다고 믿을 수 없는 경지의 기술이거든요. 그래서 그만큼 어렵기도 합니다.


regex를 다 안다
라고 하는 놈은 이 세상에 없습니다. 컴퓨터 전문 출판사 O'Reilly 에서 Mastering Regular Expressions를 출간한 저자라고 해도 regex 전문가라는 말은 해줄 수 있어도 regex의 모든 것을 다 아는 사람이라고 할 수는 없을 정돕니다. regex를 아는 대부분 컴쟁이들이 어울리지 않게 regex 쫌 할 줄 안다라고 겸손아닌 겸손을 떠는 것도 이때문입니다. 그도 그럴 것이 regex는 끝이 없습니다. 그래서 끝까지 배울 수가 없지요.

regex 실력은 이 도구를 활용하는 여러분 상상력에 달려 있거든요. 무슨소린지 배워보면 압니다. regex가 가장 빛을 발휘하는 환경은 Unix 프로그래밍이나 문서 작업에서입니다. regex 자체가 Unix 전문가들이 타자치는게 귀찮아서 조금씩 쌓기 시작한 내공이거든요. MS의 윈도우 환경에서도 조금씩 흉내를 내고 있기는 합니다만 Unix 의 기본 도구라는 점에서 ( 당연히 Linux에도 기본 도구입니다 ) 윈도우 사용자보다는 Unix 또는 Linux 사용자에게 친숙한 도구이기도 합니다.

하지만 윈도우 사용자 여러분도 regex의 맛을 느끼고 기본적인 부분을 일상생활속에서 활용할 수 있습니다. 대부분의 고급 편집기 (MS 워드 포함)에 이미 정규식이 정식 도구로 자리잡고 있거든요. 가장 기본에 충실하게 regex를 구현하고 있는 편집기로는 Ultra Editor가 있습니다. MS 워드에도 있긴 합니다만, MS가 언제나 그렇듯이 표준을 무시하고 제멋대로 만들어 놓아 거의 쓸모가 없습니다.  울트라 에디터는 쉐어웨어로 누구나 다운로드 받아 사용할 수 있습니다. [Ultra Editor 다운로드] 울트라 에디터에서 사용하는 regex 구문은 Unix 와 조금 다릅니다. Unix 호환이 되도록 설정을 바꿀 수 있지만, 이렇게 해도 조금 다르니 그냥 좀 다르다는 사실만 염두에 두세요.

일단 울트라 에디터에서 유닉스 정규식 호환이 되도록 설정을 바꿔줍니다. 고급 메뉴 설정 메뉴  찾기 탭 Unix 정규식 사용을 체크 이렇게 해줘야 Unix 랑 비슷해지고 또 그래야 여기 나온 예제 해볼 수 있습니다. 그대로 따라해도 안된다 싶으면, 이거 체크했는지 확인해 보세요. 또, 프로그래밍이 그렇듯이 정규식 또한 한치의 오차도 허용하지 않습니다. 단 한개의 오타라도 말도 안되는 결과가 나올 수 있습니다. 울트라 에디터에서 사용할 수 있는 regex는 전체 regex의 1/1000 정도밖에 되지 않습니다. 하지만, 이것만 가지고도 여러분은 regex로 마술을 부릴 수 있습니다

정규식 표현(Unix 구문)

  • \ 특수 기호의 시작을 나타냅니다. 영문으로는 원래 슬래쉬인데 한글 문서에서는 원화 표시로 나오는 그 문자 말입니다. 흔히 말하는 이스케이프 문자(escape character)를 뜻합니다. 예를 들어, n은 n이라는 문자를 말하지만 \n 이란건 개행문자(newline)를 뜻합니다. 여러분이 키보드로 쳐넣을 수 없는 특수문자를 말하는 겁니다. 왜 escape문자라고 하느냐... 원래의 의미에서 탈출해 다른 의미를 갖게 해주기 때문입니다. '\' 이 문자 자체의 문자적 의미를 되살리려면 두번 붙여 써 주면 됩니다. \\ 이렇게...
  • ^ 줄의 시작 문자와 일치합니다. 줄의 시작문자라는 것 역시 눈에 보이거나 키보드로 쳐넣을 수 있는게 아닙니다.
  • $ 줄의 끝 문자와 일치합니다. 역시 마찬가지구요.
  • * 앞에 어떤 문자가 있건 그 문자가 0번 혹은 그 이상 반복되는 걸 말합니다.

예를 들어, a* 라면 a가 안나오는 경우 (a 0번 반복), a (1번), aa (2번)...

  • + 앞에 어떤 문자가 있건 그 문자와 하나 또는 여러 개와 일치합니다. 적어도 하나의 문자가 발견됩니다.

예를 들어, a+ 라면 a가 안나오는 경우는 포함되지 않고 최소한 a가 1번은 있어야 합니다.

  • . 개행 문자 이외의 어떤 문자라도 일치합니다. a. 라고 하면 a로 시작해서 어떤 문자든 문자 하나가 따라온다는 뜻입니다. ab, ac, ad 식의 ... a 는 a뒤에 아무것도 없기 때문에 일치하지 않습니다.
  • [] 괄호 안에 열거한 문자 중 어떤 것이라도...의 뜻입니다. '[abc]D' 라고 하면 aD, bD, cD 식의 문자가 일치합니다. 순서가 있는 문자 조합인 경우, 예를 들어, [a-z] 라고 하면 알파벳 전부, [0-9] 라고 하면 숫자 전부를 말합니다. 대소문자 일치 기능을 쓰지 않으면 '[a-zA-Z]'라고 해야 알파벳 대소문자 전부를 뜻합니다. 부정할 수도 있습니다. [^a-z] 라고 하면 알파벳을 제외한 모든 문자가 됩니다.

이스케이프 문자 얘기했지요? [a-zA-Z0-9] 라고 하면 특수문자를 제외한 모든 문자라는 뜻이 됩니다. 매번 이렇게 쓰는 거 귀찮아서 유닉스 컴쟁이들은 이스케이프 문자를 활용해 이런 것도 만들었습니다.

  • \d 숫자와 일치. [0-9] 과 같습니다. 여기서 d는 digit을 말합니다.
  • \D 숫자가 아닌 문자. [^0-9] 와 같습니다.
  • \w 단어 문자와 일치. [a-zA-Z0-9]
  • \W 단어가 아닌 문자와 일치. 여기서 w는 whitespace를 말하는데요. whitespace란 공백문자를 뜻합니다. 단순히 스페이스바로 넣는 공백문자뿐 아니라 탭이나 기타 formatting의 의미를 갖는 공백, 탭, 개행문자 등등을 모두 포함합니다.
  • \n LF 문자. linefeed를 뜻합니다. 개행문자로 Unix 에서는 이것만 씁니다.
  • \r CR 문자. carriage return을 뜻합니다. 윈도우에서는 \r\n 두개를 개행문자로 씁니다.

\r 과 \n 은 실제 타자기에서 나온 겁니다. \n은 타자기에서 다음줄로 넘어가는 걸, \r은 손으로 밀어서 타자 위치를 잡는 걸 말하거든요. 컴퓨터 편집기는 이걸 알아서 하거나 여러분도 return이란 걸 치지요? Enter 키가 옛날엔 Return 키였습니다. 지금도 return이란 말 쓰기도 하구요.

  • \s 공백, 탭. 개행문자, 즉 새로운 줄과는 일치하지 않습니다. \w보다 작은 뜻.
  • \S 공백이 아닌 문자와 일치. 역시 개행 문자, 즉 새로운 줄과는 일치하지 않습니다. \W보다 작은 뜻.
  • \t 탭 문자. 탭문자 역시 눈에 보이지 않지요. 긴 문서에서 탭문자 없애느라고 손으로 하루 종일 뺑이치는 분을 본 적도 있습니다. \t 를 공백으로 찾고 바꾸기 하면 1초면 끝날 일을...

참고로 특수문자 얘기가 나왔는데, 한글은 정확하게 잡지 못할 수도 있습니다. 영문의 입장에서 보면 (regex도 알파벳을 기준을 하기 때문) 한글은 모두 특수문자에 들어갑니다. escape 문자를 사용할땐 주의하세요.

  • () 오 신이시여.... 가 드디어 나옵니다. regex의 진수는 찾기에 있지 않습니다. 바로 바꾸기에 있습니다. 앞에서 찾은 내용을 가공해서 바꾸기에 활용한다는 뜻입니다. regex가 아니라면 절대 할 수 없는 일입니다.

괄호 '()' 를 쓰는 예를 들어볼게요. Wankyu Choi <wankyuchoi@gmail.net> 식의 이메일 표기를 1000페이지 문서에서 찾아서 HTML 메일 태그로 변환하고 싶다... 이거 손으로 하려면 얼마나 오랜 시간이 걸릴까요? 잠시 고민...

다시 말해 다음과 같은 메일 태그로 바꿔주는 겁니다:

<a href="mailto:wankyuchoi@gmail.com">Wankyu Choi</a>

이런건... regex 아니면 진짜 맨땅에 헤딩을 넘어 새끼 손가락으로 물구나무 서기나 다름 없습니다. regex를 쓰면:

* 찾기 표현: (이메일 주소앞에 나오는 이름을 찾는 regex)@(이메일 주소를 찾는 regex)

* 바꾸기 표현: <a href="mailto:\2">\1</a>

라고 해주면 된다는 겁니다. ' \ ' 문자를 사용했으니 \11 과 다르다는 건 알겠지요? 바로 앞에 나온 첫번째 괄호 부분 찾기의 결과값을 뜻합니다. \2 는 두번째 괄호... 1000페이지.... 이걸 손으로 하겠다는 사람이 있다면 1주일은 넘게 걸릴 겁니다.

앞에서도 말했지만 regex의 한계는 여러분 상상력의 한계와 일치합니다. regex를 art라고 하는 이유가 여기 있어요. 쓰는 사람의 손에서 예술적 가치가 나옵니다 :-)

3부로 넘어갑니다.

이번 글에서 제가 하는 말은 그냥 무시해버리면 아무짝에 쓸모없는 멍멍  이 될지도 모르지만 잘만 쓰면 여러분이 매일 매일 생노가다하며 보내는 시간을 꽤나 줄여줄 수 있는 보물이 될 수도 있습니다.

왕도는 없어도 비법은 있다

사람들은 어떤 식으로건 일을 하고 삽니다. 돈벌이를 못하는 백수라도 손가락 까딱 안하고 누워있지만은 않으니까요.


사람들에게 똑같은 일을 시켜보면 출발점과 결과물은 같더라도 어떤 사람은 10분안에 끝날 일도 어떤 사람은 일주일이 걸리기도 합니다. 우린 이걸 능력, 또는 실력이라고 하지요.
 

누군 10분에 하는 일을 1주일 걸려 하는 사람은 다른 일거리를 줘도 역시 대부분 1주일에 하게 됩니다. 이보다 빨리 일처리를 하는 사람에겐 언제나 경쟁에서 뒤쳐지게 되지요. 
 

사람은 귀찮은걸 가장 싫어하는 동물입니다. 그래서 도구를 만들어냈지요.
 

언어만 해도 그렇습니다. 글쓰는게 귀찮아서 타자기가 만들어졌고, 급기야 두들기기만 하면 되는 컴퓨터 워드프로세서가 만들어지기도 했습니다.
인간은 도구를 사용할 줄 아는 동물입니다. 도구를 얼마나 잘 사용할 것인가... 역시 인간이 언제나 고민하는 일이기도 합니다.
살면서 뭔가 인간이라면 하지 않을 짓을 단순무식과격하게 반복하고 있다는 생각이 들때... 과거 누군가 똑같은 고민을 했을 지도 모른다는 뜻입니다.
 

그래서 또 도구를 만들고, 그 도구를 갈고 닦고, 그 도구를 100% 활용할 수 있는 비법을 만들어놓았을 수도 있다는 거지요.
이번 글에서 제가 하는 말은 그냥 무시해버리면 아무짝에 쓸모없는 멍멍  이 될지도 모르지만 잘만 쓰면 여러분이 매일 매일 생노가다하며 보내는 시간을 꽤나 줄여줄 수 있는 보물이 될 수도 있습니다.
 

수많은 골수 컴쟁이들이 (컴쟁이치고 귀찮은거 좋아하는 사람없고, 단순 노가다 좋아하는 사람이 없습니다) 만들어놓은 정규식(regular expression; 줄여서 regex)이라는 비법입니다.


컴퓨터로 노가다를 한다?

컴퓨터가 가장 잘하는 짓이 두가지가 있는데요. 하나가 숫자 놀음이고 또 다른 하나가 문자 놀음입니다. 사실 컴퓨터 내부적으로는 모두 숫자 놀음이기 때문에 문자 놀음 역시 숫자 놀음이긴 하지만...
 

숫자 놀음이야 계산기 두드리는 수준 이상의 고급 작업을 하는 경우라면 어차피 분야별로 공부를 하셔야 할테니 (예: Excel 같은 spreadsheet ) 누구나 늘상 접하는 문자 놀음에 대해서만 생각해 봅시다.
 

사실 여러분이 컴퓨터로 하는 일의 절반 이상이 문자 가지고 하는 일입니다. 그런데 편집기(editor)를 쓰건 워드(word processor)를 쓰건 알게 모르게 맨땅에 헤딩하는 경우가 수없이 많습니다. 그 맨땅에 헤딩하는 정도와 회수를 줄이자는게 이번 주제입니다.

컴퓨터 노가다의 전형적인 예

무슨 소린지 감이 잘 안오시나요? 간단하게 실험을 해보겠습니다. 여러분이 어떤 출판사에서 일을 한다고 가정해 보세요. 네오 출판사에서는 금번에 미국 대통령 연설만 몽땅 모아서 거기 나오는 어휘들로 바퀴벌레 책을 내기로 했습니다. 직원들에게 다음처럼 이런 일을 시킵니다.


  • 미국 대통령 연설문은 모조리 모아라.
  • 연설문에 나오는 모든 단어를 추출해 a,b,c 순으로 정렬해라.
  • 이렇게 만든 단어 목록을 가지고 3자리 이상되는 단어만 다시 뽑아 단어집을 만들어라. ( 세자리 미만은 큰 의미가 없으니까 )

예를 들어, 미국 대통령 연설문이 딱 100개 된다고 해보지요. 더 되겠지만 그정도만 된다고 칩시다. 네오퀘스트 특강(실전 독해)에 사용된 클린턴 연설문에 나오는 단어가 중복을 허용한 상태로 8,000개쯤 됩니다.
 

이게 100개면 800,000개란 얘기지요? 800,000 단어를 손으로 추려서 중복된거 골라내고... 이걸 다시 3자리 이상만 골라내고...
내가 그런 과격한 노가다를 할 가능성이 있을까?
 

이렇게 생각하실 지 모르지만 그냥 한가지 예일 뿐입니다. 규모는 작아도 하루에도 몇번씩 우리는 이런 일을 하고 삽니다.
 

짧은 문서의 찾고 바꾸기(search and replace)일 수도 있고, 여기 나온 예처럼 몇달이 걸리는 수작업일 수도 있습니다. HTML 문서 소스를 뽑아 태그만 몽땅 없애고 본문만 남기는 작업일 수도 있고, 스팸 회사에서 게시판 뒤져가며 이메일만 추출해내는 일일 수도 있습니다.
 

그래도 무슨 소린지 와닿지 않는다면 생활속에서 흔히 볼 수 있는 예를 하나 들어볼까요?
 

여러분이 웬 긴~~~ 문서를 읽다가 몇년도인가 재밌는 일이 일어났다고 하는 걸 봤다고 칩시다. 한 일주일쯤 지나고 나서 친구에게 그 얘기를 하다 다시 해당 부분을 찾아보려니 그 긴~~~ 문서에서 어느 부분이었는지 또는 몇년도였는지조차 기억이 안나는 겁니다. 이 문서가 또 100페이지쯤 되고 대충 어느 위치였는지도 모른다면 해당 부분을 찾는데 시간이 얼마나 걸릴까요?
 

실제로 이런 일을 종이책 뒤지듯 하루 종일 뒤지는 분들도 있습니다. 그나마 편집기나 워드의 찾기(find) 기능을 활용하는 분이라면 형편이 좀 나은 거지요.
 

앞에 나온 단어찾기 노다가... 여러분이 회사에서 살아남으려면 죽어도 해야 하는 일이라면, 며칠, 아니 몇달 걸리면 끝날까요?


아마 이글을 읽는 분의 컴퓨터 숙련도에 따라 답이 달라질 겁니다. 10초를 외치신분 혹시 있나요? ;-)
 

이런게 바로 사람이 해야할 일이 아니라 컴퓨터가 해야할 일입니다. 컴퓨터란 놈이 제일 잘하는 짓이니까요. 그럼 컴퓨터 숙련도에 따른 시간을 재 볼까요?


  • 프로그래밍이 가능한 엔지니어 - 사용하는 컴퓨터의 처리속도에 따라 다르지만 대충 10초 내에 저 일 끝날 수 있습니다. 또, 프로그램으로 만들어 놓을 것이기 때문에 다른 어떤 문서를 가져다 줘도 저 기능은 10초내에 모든 문서를 해결할 수 있습니다. 스스로 도구를 창조하고, 동일한 종류의 일에 대해서는 언제나 이 도구를 사용합니다.
  • 정규식 표현을 알고 있는 파워 유저 - 앞에서 이름만 소개한 regular expression 이라는 겁니다. 사실 배우기가 무지 까다로워서, 아니 제대로 가르쳐주는 사람이 없어서, 그만큼 알기도 어려워서, 이 빈곤의 악순환으로 극소수 컴쟁이들만이 향유하는 그야말로 인간이 만들어낸 최고의 논리 장난감입니다. 이걸 아는 사람이면 10초는 아니더라도 저 일 1시간내에 끝납니다.
  • 프로그램도 정규식도 모르는 그냥 유저 - 역시 숙련도에 따라 다르지만 길게는 며칠, 심하게는 1년이 걸릴 지도 모르지요. 또 정확성을 기대할 수도 없습니다. 손으로 하는거라 빼먹을 수도 있고, 짜증나서 안할 수도(눈가리고 아웅) 있으니...

한때 Python이란 언어를 만든 그 이름도 야시꾸리한 Guido Van Rossum 이란 천재 컴쟁이가 Computer Programming for Everyone이란 프로젝트를 진행한적이 있습니다. 이거 조금만 하면 저 사람들 뺑이치는걸 백분의 1, 아니 백만분의 1로 줄일 수 있을텐데... 하는 안타까움에 시작한 자선 사업이었데요. 근데 자금 부족, 중생들의 참여가 형편없어 실패했다는군요. 선각자의 뜻이 그대로 실현이 될 수는 없는 노릇이듯이... 
 

여기서 제가 하고자 하는 얘기는 거기까지 가지도 않습니다. 물론 프로그래밍의 아주 기본적인 것만 배워도 여러분 삶이 얼마나 윤택해질 지 마구 설파하고 싶지만 모든 이에게 프로그래밍이 좋고 즐거운일은 될 수 없을테니까요.

하지만, 정규 표현식(regular expression) 정도라면 충분히 가능성이 있다고 생각합니다. 그 정도만 되도 여러분 삶이 윤택을 넘어 젖과 꿀이 흐르는 가나안이 될 수도 있다고 믿거든요. 10초면 끝날 수 있는 일을 1주일 걸려 해야만 한다면, 비극이 아닐까요? 


차리리 하루 정도 걸린다고 구라치고 잽싸게 끝낸다음 나머지 시간에 땡땡이를 칠 수 있는 여유를 갖는 것... 그게 진정한 호모 사피엔스, 인간의 모습이 아닐까요?
 

비법 전수 2부에 이어집니다.



http://www.gethifi.com/tools/regex

위 사이트에서 정규식 연습 할수 있음!!

+ Recent posts