[Regular Expression] 정규표현식 앵커(Anchor)와 매칭 위치 제한

앵커는 정규 표현식의 일치 위치를 고정하는 메타문자(들)을 말합니다.

앵커는 문자가 아니며, 문자와 일치하지도 않습니다. 문자의 앞, 뒤, 또는 문자 사이의 위치를 가리키는 “위치 지시자”입니다. 따라서 앵커로 일치를 했다고 해도 앵커 자체는 길이가 0입니다.

앵커로 일치하는 위치는 제한적이며, 문자열의 시작 위치, 또는 끝 위치만 일치할 수 있습니다. 예외적으로 단어 문자의 앞뒤 경계와 일치하는 메타문자인 “\b”가 있습니다.

앵커는 위치 조건을 충족해야 일치가 발생하는 유일한 메타 문자입니다. 닻을 내려서 배의 위치를 고정하는 것처럼, 앵커를 사용해서 매칭을 시작하는 위치, 또는 끝 위치를 고정한다고 이해하면 됩니다.

문자열의 시작 위치에 일치 - 캐럿(^)

정규 표현식 매칭 시작을 입력 문자열의 처음 위치로 고정합니다. 입력 문자열의 첫 문자가 일치하지 않으면 매칭을 즉시 종료합니다.

단, 문자 클래스의 첫 위치에 표시하는 캐럿은 위치용 메타문자가 아닙니다. 다른 의미로 사용하므로 주의해야 합니다. 문자 클래스의 여는 대괄호([) 바로 뒤에 오는 캐럿은 문자 클래스에 나열된 문자를 제외한 나머지 문자와 일치를 하는 “not”의 의미입니다.

당연하지만 정규 표현식 시작 위치에 캐럿을 사용하면 한 개의 일치 결과만 반환할 수 있습니다.

캐럿은 정규 표현식 맨 앞에만 올 수 있습니다. 그 외의 위치에서 사용하면 정규 표현식과 일치하는 결과가 없게 됩니다. 주의해야 합니다.

정규 표현식 /^abc/는 문자열 시작이 “abc”면 일치하지만, /a^bc/는 아무 것과 일치하지 않습니다. 리터럴 문자 “a^bc”와도 일치하지 않습니다. 리터럴 문자로 일치하려면 /a\^bc/와 같이 캐럿을 이스케이프 해야 합니다.

문자열의 끝 위치에 일치 - 달러($)

정규 표현식의 끝 부분을 입력 문자열의 끝 부분과 일치합니다. 입력 문자열의 끝 문자가 정규 표현식 끝과 일치하지 않으면 매치를 종료합니다.

정규 표현식 끝 위치에 달러를 사용하면 한 개의 일치 결과만 반환할 수 있습니다. 달러 문자는 정규 표현식 맨 끝에만 올 수 있습니다. 그 외의 위치에서 사용하면 정규 표현식과 일치하는 결과가 없게 됩니다. 주의해야 합니다.

정규 표현식 /abc$/는 문자열 끝이 “abc”면 일치합니다. /ab$c/는 아무 것과 일치하지 않습니다. 리터럴 문자 “ab$c”와도 일치하지 않습니다. 리터럴 문자로 일치하려면 /ab\$c/와 같이 달러를 이스케이프 해야 합니다.

멀티라인 플래그(Flag) 사용

여러 행으로 된 문자열에서 앵커 메타문자로 문자열의 일치하는 시작과 끝 위치를 한정할 때, 각 행마다 행의 시작과 끝 위치에 일치를 하고 싶을 때 사용하는 플래그 (Modifier)입니다.

플래그는 “m”을 사용합니다. 앵커 전용 플래그입니다. “m” 플래그를 사용하면 각 행 별로 시작 위치(^), 또는 끝 위치($)를 일치합니다. 

정규 표현식 앵커 메타문자 중에는 문자열 처음과 일치하는 \A, 그리고 문자열의 끝과 일치하는 \Z, \z가 추가로 있습니다.

\A는 캐럿(^), \Z, \z는 달러($)와 같은 기능을 합니다. 이 메타문자는 멀티라인 플래그 “m”을 대체합니다.

\Z(대문자 Z)는 달러($)와 플래그 “m”을 사용한 것과 같습니다. 줄 바꿈 앞의 마지막 문자와 일치합니다.

\z(소문자 z)는 플래그 “m”이 없는 달러($)와 같습니다. 전체 문자열의 마지막 문자와 일치합니다.

단, \A, \Z, \z 메타문자는 자바스크립트에서는 지원되지 않아 사용할 수 없습니다. (사용해도 정규 표현식 일치가 되지 않습니다.)

단어(Word)의 경계와 일치하기(\b)

단어 메타문자(\w)와 함께 사용하는 메타 문자입니다. 단어 메타문자 \w는 “[A-Za-z0-9_]+”와 같습니다.

알파뉴메릭(Alphanumeric)과 언더바 문자로 구성된 연속 문자열을 정규 표현식 에서는 “단어”로 정의합니다.

\w는 문자 1개입니다. 착각하면 안됩니다. 단어 문자와 단어 문자가 아닌 비 단어 문자 사이의 경계선을 일치하는 메타 문자입니다.

\b는 문자를 가리키는 것이 아니며, 경계점을 나타내는 위치 표시자입니다. \b로 일치하는 단어의 경계는 \w로 일치한 단어 문자의 앞, 또는 뒤에 \W에 해당하는 비 단어 문자여야 합니다.

이때 단어 문자에 해당하는 문자를 정규 표현식에 표현할 때 꼭 메타문자인 \w를 사용해야 하는 것은 아닌 것에 주의해야 합니다.

단어 문자는 [a-zA-Z0-9_] 문자 중 한 개를 의미하며, /[is]+\b/g 정규 표현식은 “This is a word.” 문자열에서 [“is”, “is”] 2개를 일치합니다.

/\b\w+\b/ 정규 표현식은 연속된 단어 문자 앞과 뒤에 단어 문자가 아닌 문자가 있어야 합니다. “This is word.” 문자열은 [“this”, “is”, “word”]를 일치합니다.

 

단어 경계(Word Boundary)라는 단어에서 알 수 있듯이, 메타문자인 \b는 단어 단위로 일치를 할 때 단어 단위로 구분을 하는 경계 역할을 합니다.

단어 문자와 비 단어 문자를 명확하게 구분할 수 있기 때문에 단독으로 사용되는 단어를 분리할 수도 있습니다.

“666은 6이 3번 나옵니다.” 문자열에서 다른 숫자의 일부가 아닌 단독으로 사용된 “6”만 찾고 싶다면 /\b6\b/g처럼 6을 단어 경계로 감싸면 됩니다.

자바스크립트에서는 한글이 “비 단어 문자”이기 때문에 단어 경계를 표시하는 \b가 올바르게 적용되지 않습니다.

\w 메타 문자 등으로 한글 단어 매칭이 가능하지만 전역으로 유니코드를 사용하지 않는 개발 언어에서는 유니코드 매칭을 위한 플래그를 별도로 켜야합니다. 자바에서는 “UNICODE_CHARAC TER_CLASS” 플래그를 사용해야 하고, PHP에서는 “u” 플래그를 사용해야 합니다.

부정 단어 경계

단어 경계를 표시하는 \b의 반대 의미로 단어 경계가 아닌 위치를 말하며 \B로 표시 합니다.

단어 경계가 아닌 위치를 알려면 단어 경계가 되는 위치부터 알아야 합니다. 단어 경계는 다음 4가지 중의 하나가 됩니다.

 

  • 문자열의 맨 앞 첫 번째 문자가 단어 문자일 때 문자열의 맨 앞 위치
  • 문자열의 맨 뒤 마지막 문자가 단어 문자일 때 문자열의 맨 뒤 위치
  • 단어 문자와 바로 뒤에 이어서 오는 비 단어 문자 사이 위치
  • 비 단어 문자와 바로 뒤에 이어서 오는 단어 문자 사이 위치

 

정규 표현식으로 표현하면 ^\w, \w$, \W\w, \w\W 4가지가 됩니다.

단어 경계가 단어 앞/뒤에 모두 올 수 있기 때문에 길게 풀어서 4가지로 나누어 설명 했지만 인접한 단어 문자와 비 단어 문자(문자열 양 끝단 포함) 사이가 단어 경계가 됩니다.

단어 경계가 아닌 것이 부정 단어 경계가 되므로 앞의 4가지 조건에 부합하지 않는 다음 2가지가 부정 단어 경계가 됩니다.

 

  • 단어 문자와 바로 뒤에 이어서 오는 단어 문자 사이 위치
  • 비 단어 문자와 바로 뒤에 이어서 오는 비 단어 문자 사이 위치

 

정규 표현식으로 표현하면 \w\w, 또는 \W\W 두 가지가 됩니다.

“This is a word.” 문자열에서 부정 단어 경계 사이에 있는 단어 문자만을 고르는 /\B\w+\B/g 로 일치를 하면 [“hi”, “or”]가 매치됩니다.

 

부정 단어 경계는 개발 언어에 따라서는 완벽하게 지원되지 않는 경우가 있습니다. 사용할 때는 호환성 여부를 확인한 후 사용해야 합니다.

위치를 한정하는 앵커 메타문자 사용 핵심 요약

매칭하는 문자(열)가 매칭하려는 전체 문자열의 시작/끝, 또는 단어의 시작 끝 위치부터 매칭이 되는지 확인하도록 위치를 한정하는 메타문자 들입니다. 

 기호

의미 

^

입력 문자열의 처음 시작 위치부터 매칭해서 일치하는지 확인합니다.

정규표현식 /^T/는 “the Times”는 매치되지 않으며 “The Times”는 매치 됩니다.

$

입력 문자열의 끝 위치 문자가 매치되는지 확인합니다.

정규 표현식 /story$/는 “What is the story of never ending story” 문자열 에서 끝 부분 문자열 “story”가 매치됩니다.

\b

단어의 경계가 일치하는지 확인합니다. “\b문자” 가 되면 단어의 시작 위치부터 일치하는지를 확인하고, “문자\b”가 되면 단어의 끝에서 일치하는지를 확인 합니다.

정규 표현식 /\bst/ 는 단어 “never ending story”에서 “story” 단어의 시작 부분이 매치되어 “st”를 반환하며, 정규 표현식 /ry\b/ 는 “story” 단어의 끝부분 “ry”와 매치됩니다.

/\bstory\b/ 는 “ story “처럼 공백으로 분리되어(또는 입력 문자열의 끝) 양쪽 끝이 모두 일치하는,  전체 단어를 확인합니다.

\b는 단어의 끝 그러니까 단어가 아닌 문자로 분리되어 있는 문자열(단어)의 시작, 끝 경계 부분을 기준으로 비교합니다.

\B

\b와 반대로 단어 경계가 아닌지를 확인합니다.

단어 경계를 매칭하는 \b 와 반대입니다. \b는 \b가 있는 방향이 단어 경계여야 하지만, \B는 \B가 있는 방향이 단어 경계가 아니어야 합니다. 정규 표현식 /\B문자/은 \B가 있는 방향(왼쪽)이 단어 경계가 아니고 “문자”가 일치하는지를 찾습니다.

“story” 단어에서 정규 표현식 /\Bry/ 는 매치되지만 /\Bst/는 매치되지 않습니다. 같은 방식으로 /\Bor/도 매치가 됩니다. \B가 있는 방향이 단어 경계가 아니기만 하면 됩니다.

x(?=y)

x 뒤에 y가 나오면 x를 매칭 결과로 반환합니다. x 뒤에 y가 오는 조건부 매칭 입니다.

/love(?=him|her)/ 정규 표현식은 “love” 뒤에 “him” 또는 “her”가 오면 “love”를 매칭합니다.

x(?!y)

x(?=y) 매칭 조건과 반대입니다. x 뒤에 y가 오지 않으면 x를 매칭하는 조건부 매칭입니다.

정규 표현식 /\w(?!(#|.))/은 “#” 또는 “.”이 뒤에 오지 않는 문자열을 매칭합니다.

(?<=y)x

x 앞에 y가 나오면 x를 매칭합니다. x 앞에 y가 오는 조건부 매칭입니다.

정규 표현식 /(?<=he|she)love/은 “love” 앞에 “he” 또는 “she”가 오면 “love” 를 매칭합니다.

(?

(?<=y)x 매칭 조건과 반대입니다. x 앞에 y가 오지 않으면 x를 매칭하는 조건부 매칭입니다.

정규 표현식 /(?

  • x, y는 문자입니다.