본문 바로가기

Daylogs/Javascript

정규식 단어 경계 메타 문자 \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로 처리할 수 없다는 것이다.

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

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


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




  • 1234 2013.03.04 16:50

    저도 이 책 보다가, /B-/B 가 왜 공백-공백을 선택하는지가 영 이해가 안되서 구글 찾다가 들렸는데,
    설명 때문에 쉽게 이해할 수 있었어요^^ 감사합니다~