정규식 단어 경계 메타 문자 \b 의 정확한 이해

발생일: 2013.02.18

문제:
우리 부부는 주말마다 커피숍에 가서 책을 읽는데,
어제는 날이 좋아서 남양주에 있는 고당이라는 카페로 나들이를 갔다.

작년에 한 번 다녀왔던 곳인데, 한옥 카페이고 분위기도 괜찮다.
좀 비싼 데다 오래 기다려야 하는 게 흠이긴 한데, 딱 드라이브하기 좋을 만큼의 거리라 즐겁게 다녀왔다.

그치만, 거리도 있고 해서 오래 앉아있을 것도 아니어서, 
가볍게 후딱 읽을 셈으로 책장에서 가장 얇은 '손에 잡히는 정규 표현식'을 뽑아 들고 갔다.

정규식은 나름 잘 알고 있다고 생각해서 그닥 읽을 계획이 없던 책이었는데,
읽어보니 어려운 개념도 아주 쉽게 잘 설명해놓아서 많이 배울 수 있었다.

예전에 먼저 읽었던 아내가,
단어의 경계를 나타내는 \b 메타 문자의 예제 부분에 물음표를 쳐둬서 그 부분은 특히 유심히 봤다.
\b 와 \B 를 비교해둔 예제문이었는데, 나도 많이 헷갈리더라.

사실, \b 는 단순히 단어 구분의 용도로만 쓰고 별 것 없다고 생각했었는데,..
잘 모르겠더라. -..-;

이참에 제대로 알고 넘어가야겠다 싶어서 정리해봤다.


해결책:

\d 나 \w, \s 등과 같은 메타 문자들이 '특정 텍스트의 집합'을 매칭시키는 것과 다르게,
\b 는 단어의 `경계` 위치를 가리킨다. (b = boundary 를 의미한다)

여기서 '단어'는 \w 와 일치하며 [a-zA-Z0-9_]와 동일하다.
즉, 단어와 단어가 아닌 문자와의 사이를 가리키는 것이다.

위치를 가리키는 것이기 때문에, 패턴이 일치하더라도 매치되는 길이는 0이다.
이런 이유 때문에 좀 헷갈리는데, 문장에서 각 단어의 경계를 표시해보면 쉽게 이해할 수 있다.


  Raindrops on roses, and whiskers on kittens.

위 문장에서 단어의 경계, 즉 메타 문자 \b 는 아래와 같이 | 를 표시한 위치를 가리킨다.

  |Raindrops| |on| |roses|, |and| |whiskers| |on| |kittens|.


이 문장에서  /\bo.\b/ 를 매치시킨 결과는 다음과 같다.

  |Raindrops| |on| |roses||and| |whiskers| |on| |kittens|.

패턴이 단어의 경계 사이에 있는 o와 나머지 한 문자를 나타내기 때문이다.


\B 는 \b와 반대로 동작하는데, 이것도 각 위치를 표시해보면 이해하기 쉽다.

  R|a|i|n|d|r|o|p|s o|n r|o|s|e|s, a|n|d w|h|i|s|k|e|r|s o|n k|i|t|t|e|n|s.

따라서, /\Bo.\B/ 와 매치시키면 아래와 같다.

  R|a|i|n|d|r|o|p|s o|n r|o|s|e|s, a|n|d w|h|i|s|k|e|r|s o|n k|i|t|t|e|n|s.


주의할 것은, 정규식에서의 '단어'는 한글과 같은 2바이트 문자를 포함하지 않기 때문에,
한글의 경계는 \b로 처리할 수 없다는 것이다.

한글의 경계를 판단하려면, 전후방탐색으로 한글이 아닌 문자와의 경계를 판단하는 것이 좋다.

  /(?<=[^가-힣])대상문자(?=[^가-힣])/
  (자음과 모음까지 문자로 인식하려고 한다면, [^ㄱ-ㅎㅏ-ㅣ가-힣] 를 사용하면 된다)


자바스크립트와 같이 후방 탐색을 제공하지 않는 정규식 엔진이라면,
정규식으로만 걸러내는 것보다는, 해당 케이스에 맞는 별도의 로직을 작성하는 것이 좋겠다.




카테고리

분류 전체보기 (710)
About me. (6)
Daylogs (675)
영어공부 (0)
My works - 추억 (29)
비공개 (0)