Here's my dents in the universe

Regex로 당신의 검색에 날개를 달아주세요


1. Intro.

정규표현식(Regular expression, Regex)에 관한 재미있는 일화*가 있어 소개한다. 1972년, 벨 연구소에 다음과 같은 문의 전화가 왔다고 한다.

“휴대용 계산기를 거꾸로 들면 숫자 중 일부가 글자가 된다는 것을 알게 됐습니다. 예를 들면, 3은 E가 되고, 7은 L이 되죠. 계산기를 거꾸로 들었을 때 만들 수 있는 단어가 어떤 것들이 있는지 알아봐주실 수 있을까요?”

당시 벨 연구소에서 일하던 브라이언 커닝햄(주석)은 계산기를 거꾸로 들었을 때 만들어질 수 있는 알파벳이 B, E, H, I, L, O, S 임을 확인하고, 키보드 앞에 앉아 다음과 같은 명령어를 입력했다고 한다. grep '^[behilos]*$' /usr/dict/web2

/usr/dict/web2 파일은 Webster’s Second International 사전에 등재된 234,936 개의 단어를 모두 포함하고 있는 파일이다. 커닝햄은 순식간에 계산기를 뒤집어 만들 수 있는 263개의 단어를 찾아낼 수 있었고, 그 단어 목록을 프린터로 출력해 전화를 걸었던 이에게 보내주었다고 한다.

위와 같은 특수한 상황이 아니더라도, 코드를 작성하다보면 특정한 패턴을 찾고싶은 경우가 생긴다. 찾고싶은 텍스트가 있다면 Cmd(Ctrl) + F로 쉽게 찾아낼 수 있겠지만, 패턴은 그렇지 않다. ‘알파벳 B, E, H, I, L, O, S 로만 이루어진 단어’를 어떻게 검색할 것인가? 정규표현식으로는 가능하다. 정규표현식은 당신의 검색에 날개를 달아준다. 그 문법을 배워보자.

2. How to use?

1) 표기

Regex 리터럴은 슬래시(“/”)로 감싸 표현한다. /찾고싶은_패턴/ 과 같이 표현하는 식이다. 간결한 표기를 위해, 아래 글에서는 슬래시를 생략하기로 한다.

2) 단순 패턴

단순 패턴은 문자열을 있는 그대로 대응시키고 싶을 때 사용한다. 우리가 일반적으로 사용하는 검색 방식과 같다. ‘abc’라는 패턴은 문자열에서 정확히 ‘abc’라는 문자가 모두 함께, 순서대로 나타나야 대응된다.

3) 특수 문자

Regex는 특수 문자를 사용할 때 빛을 발한다. 문법과 함께 예시를 보면서 이해해보도록 하자.

그룹

문자

개수 Quantifier

이 외

3. Example

Regex는 아무리 설명을 읽어도, 실제로 작성하기 전까지는 감이 오지 않는다. 작성한 regex에 매칭되는 문자열을 실시간으로 확인해볼 수 있는 웹사이트를 켜놓고, 실습해보도록 하자.

특정 문자만 매칭하기

(MATCH) can  
(MATCH) man  
(MATCH) fan  
(SKIP)  dan  
(SKIP)  ran  
(SKIP)  pan 
--------- 
[cmf]an      # 문자셋을 사용해 c, m, f로 시작하는 문자열만 매칭된다.
[^drp]an     # 문자셋과 ^을 함께 사용해 d, r, p로 시작하는 단어는 제하고 매칭된다.

반복되는 문자 매칭하기

(MATCH) wazzzzzzup 
(MATCH) wazzzup 
(SKIP)  wazup 
--------- 
waz{2,}up     # quantifier를 이용. 두번째 인자를 생략하면 제한 없이 매칭된다.

(MATCH) aaaabccc
(MATCH) aabbbbc
(MATCH) aacc
(SKIP)  a
---------
a+b*c+      # a: 1개 이상, b: 0개 이상, c: 1개 이상인 경우 매칭되는 패턴이다.

공백 매칭하기(MATCH)

(MATCH) 1. abc
(MATCH) 2.   abc
(MATCH) 3.      abc
(SKIP)  4.abc
---------
\d\.\s+abc   # 숫자 온점 이후에 공백이 1개 이상 포함된 문자열만 매칭된다.
             # 앞에서부터 차례로 읽으면 된다.
             # \d(숫자)\.(온점)\s+(공백이 1개 이상)abc(단순 패턴)

시작과 끝에 매칭하기

(MATCH) Mission: successful 
(SKIP)  Last Mission: unsuccessful 
(SKIP)  Next Mission: successful upon capture of target 
---------
^Mission: successful$  # ^와 $ 사이의 패턴이 정확히 라인의 시작과 끝에 매칭된다.

그룹 매칭하기(MATCH)  

(MATCH) Mission: successful 
(SKIP)  Last Mission: unsuccessful 
(SKIP)  Next Mission: successful upon capture of target 
---------
^Mission: successful$  # ^와 $ 사이의 패턴이 정확히 라인의 시작과 끝에 매칭된다.
                       # 이것 역시 앞에서부터 차례로 읽으면 된다.
                       # ^(라인 시작)file(단순 패턴).+(모든 문자가 1개 이상)\.(온점)pdf(단순 패턴)$(라인 끝)

4. Outro.

Regex와 관련한 유명한 농담이 있다.

어떤 사람들은 문제에 맞닥뜨렸을 때 ‘정규표현식을 이용해서 해결해야지’ 생각하곤 한다. 오래지않아, 그들은 이제 문제가 2개가 되었음을 깨닫는다.

Regex는 생각만큼 쉽게 익숙해지지 않는다. 이정도면 다 알게 되었다고 생각하는 순간, 다시 낯설게 느껴지는 경우가 생길 것이다. 처음부터 완벽하게 숙달할 필요는 없다. 필요해질 때마다 한 번씩 다시 찾아본다면, 어느새 익숙해진 자신을 발견하게 될 것이다.

Reference.