() 메타문자
어딜가든 ()
를 그룹핑 문자로 쓰는 것 같다. 우리는 보통 ()
문자를 연산의 순서를 명확하게 하거나 문맥을 좀 더 명확하게 구분하고 싶을 때 사용한다.
|
|
()
를 정규식에서 쓰는 이유도 범위를 구분짓기 위해 쓴다. {}
는 반복의 양을 나타낼 때 쓰인다..
예제1
|
|
regexp
는 a~d 사이의 문자 하나와 1~5 사이의 문자가 5번 반복되는 패턴을 표현한다(6개 문자). 예를들어,a12345
와 같은 문자열이 매칭된다.regexp2
는 a~d 사이의 문자 하나와 1~5사이의 문자 하나, 즉 두개의 문자가 5번 반복하는 패턴을 표현한다(10개 문자). 예를들어,a1a2a3a4d5
와 같은 문자열이 매칭된다.
예제2
|
|
txt에서는 tuesdays
고 regexp에서는 tuesday
인 것에 주의하자. 이 예제에서 text를 regexp로 검사하면 tuesdays가 매칭된다. 그런데 이는 원하는 결과가 아니다. \b
경계 메타문자를 쓴 의도는 정확하게 에누리 없이 tuesday
를 찾으려는 것이었을 것이다. 따라서 tuesdays
를 검색 결과에서 제거하기 위해 다음과 같이 ()
를 쓸 수 있다.
|
|
이처럼 ()
를 써서 정규식을 그룹핑 시켜주면, 간단히 원치 않는 결과를 피할 수 있다.
그룹의 값 사용(\1, \2, …)
?:
메타문자는 정규식의 그룹 문맥에서 쓰기위해 도입된 것이다. 그룹을 포착한다는 의미의 Capturing Groups란 이름이 붙어있다. 이 메타문자를 이해하려면 정규식에서 그루핑한 특정 패턴의 값을 쉽게 가져다 쓸 수 있다는 사실을 알아야 한다.
|
|
위의 예제는 날짜 정규식의 간단한 예다. 2020-01-01
과 같은 문자열과 매칭된다. 이 정규식 에서는 [-./]
의 패턴이 2번 나오는데, 이를 그룹핑화 해서 표현하면 다음과 같이 할 수 있다.
|
|
설명하자면, 첫번째로 나오는 [-./]
는 ()
로 그룹핑 했고, 두번째로 나오는 [-./]
는 \2
를 써줬다. 여기서 \2
의 의미는, 두번째로 나오는 그룹의 값을 쓰겠다는 말이다(패턴이아닌 값인 것에 주의). 위의 예제에서 첫번째 그룹은 (\d{4})
이고 두번째 그룹이 (-./)
이므로 두번째 그룹의 (-./)
자리에 오는 값이 \2
자리에 들어가게 된다.
?: None Capturing Groups
정규식의 그룹 문맥에서만 사용되는 메타 문자가 있는데, ?:
과 다음에 살펴볼 ?=
이 그것이다. ?
는 단독으로 쓰일 때, 문자 0개 혹은 1개와 매칭되는데 ?:
와 ?=
는 그것과 의미가 완전히 다르다.
|
|
이 예제는 위의 예에서 맨 앞의 그룹에 ?:
만 붙인 것이다. 이 때, \2
가 가리키는 값은 ([-./])
이 아닌 (\d{1,2})
이 매칭시킨 값이다. 따라서 우리는 ?:
를 쓰면, 그룹의 순서에서 제외된다는 것을 확인할 수 있다. 위의 예제에서는 \2
대신 \1
을 써야 원하는 결과를 얻을 수 있다.
?= Lookahead Groups
정규식에서 ?=
메타문자로 input 문자를 필터링 할 수 있는데, 이 말은 그룹의 패턴을 차례대로 일치하는지 살펴보겠다는 말이다. 예를 들어 보겠다.
|
|
위의 예시에서는 4개의 그룹핑 패턴이 존재하고, 그 그룹 패턴에는 모두 ?=
기호가 들어가 있습니다. 맨 마지막에 .*
이 패턴 검사를 위해 사용할 input text가 되는 것이다.
그러니까 위의 정규식을 말로 설명하자면, 모든 문자에 대해 검사하는데(.*
), 그 문자는 8자 이상이어야 하고((?=.{8,})
), 대문자((?=.*[A-Z])
) 혹은 소문자((?=.*[a-z])
) 혹은 숫자문자((?=.*[0-9])
)가 0개 이상인 패턴을 찾아내는 정규식이 되겠다.
?! Negative Lookahead Groups
?=
메타문자가 매칭 되어야 하는값을 필터링 하는 반면, ?!
메타문자는 매칭 되어선 안되는 값을 필터링 해준다. 예를들어, 위의 예제에서 2번째 그룹인 (?=.*[A-Z])
를 (?!.*[A-Z])
로 바꿔보자.
|
|
이제 이 정규식은 문자가 8자 이상, 소문자와 숫자가 있어도 되는데, 대문자는((?!.*[A-Z])
) 하나라도 있으면 안된다는 뜻이다. 그러니까 ?=
에 not
을 붙인게 ?!
인 것이다.