티스토리 뷰

정규표현식에서 패턴을 입력문장에 매치한다는 것은 입력문장에서 패턴 전체의 규칙에 만족되는 부분을 찾는 것입니다. 매치되는지 여부를 참 거짓으로 돌려주기도 하고 앞의 글에서 살펴본 도구에서처럼 매치되는 부분 문자열을 모두 찾는 것도 가능합니다. 여기까지는 패턴에 매치되는 부분 전체를 다루게 됩니다.

그런데 캡처그룹은 거기서 한걸음 더 나아가서 매치된 부분에 속하는 일부를 다시 분리하여 돌려주는 방법입니다. 예를 들어 이메일에 매치된 문자열 부분을 찾았다면 거기서 @ 앞에 있는 아이디 부분만 따로 떼내고 싶을 수 있을 것입니다. 또는 끝에 도메인이 .kr인 것에서 앞부분만 구분해 내고 싶을 수도 있지요. 또는 패턴에 매치된 부분에서 일부를 바꿔치기 할 수도 있습니다. 예를 들다면 kyonggi.ac.kr로 되어 있는 모든 이메일 주소를 kgu.ac.kr로 바꾸려고 하는 경우를 생각해 볼 수 있습니다. (물론 바꾸기 기능도 정규표현식에서 제공되고 있습니다) 그러면 이메일로 매치하고 그 중에서 다시 한번 매치하거나 찾으려면 코드가 복잡해지게 될 것입니다.

이럴 때 사용할 수 있는 것이 패턴 내에서의 캡처 그룹입니다. 패턴 안에서 일부분을 캡처 그룹으로 표시하면 매치된 문자열 중에서 캡처 그룹에 해당하는 것을 따로 뽑아낼 수가 있습니다. (Pattern객체의 메소드를 이용해서...)

패턴에서 캡처 그룹은 소괄호 ( ... )를 이용해서 표시합니다. 먼저 패턴에서 어떻게 캡처 그룹을 표시할 수 있는지 예를 통해 살펴보겠습니다.

입력 중에서 "와 "로 묶인 단어 부분을 찾고자 한다면 패턴을 다음과 같이 쓸 수 있습니다.

\"(\w+)\"

이것은 "로 묶인 단어 부분인데 그 중에서 단어에 해당하는 부분만 ( ... )로 캡처 그룹을 표시했습니다. 그러면 이것을 이용해서 얻어지는 부분 문자열은 다음과 같이 구해집니다. 현재 제공된 RegexTestHarnessEjlee 클래스에서 (3)번 메뉴를 이용하면 전체 패턴에 매치된 부분에 추가하여 캡처링 그룹에 매치된 부분을 다로 괄호 안에 출력해 줍니다. 

(1) regex 먼저    (2) input 먼저   (3) 그룹찾기   (기타) 종료.. 3

regex: \"(\w+)\"
input: abcd "abcd" abcd "abcd
찾은 문자열  ""abcd"" (5, 11)
	(abcd)  
input: aaa *bbb" ccc"ddd"eee"ff"g
찾은 문자열  ""ddd"" (13, 18)
	(ddd)  
찾은 문자열  ""ff"" (21, 25)
	(ff)  
input: 

하나의 패턴 안에서 캡처링 그룹은 여러 개가 될 수 있으므로 각 그룹에 대해 번호를 매겨 구분합니다. 각 그룹은 괄호로 묶이는 부분인데, 괄호 안에 또 괄호가 들어갈 수 있으므로 중첩된 괄호에 대해서는 트리 형태로 표현했을 때 선방문 순서로 번호가 매겨집니다. 전체 패턴을 0번으로 하고 이것을 루트로 내부에 중첩된 부분을 자식으로 보고 트리 형태를 만들 수 있습니다. 다음 예제를 통해 캡처그룹의 번호가 어떻게 매겨지는지 확인해 봅시다.

\d*(a+(b+(c+)(d+)e+)\d*

(1) regex 먼저    (2) input 먼저   (3) 그룹찾기   (기타) 종료.. 3

regex: \d*(a+(b+(c+)(d+)e+))\d*
input: 33aabbcdee44
찾은 문자열  "33aabbcdee44" (0, 12)
	(aabbcdee)  (bbcdee)  (c)  (d)  
input: 1234abcdefg
찾은 문자열  "1234abcde" (0, 9)
	(abcde)  (bcde)  (c)  (d)  
input: 

위의 예에서 매치된 전체 문자열이 0번, 제일 바깥의 괄호가 1번이고 그룹의 개수만큼 캡처그룹이 출력됩니다. 이 때 중첩구조에서 제일 바깥이 먼저 출력되고 그 다음에 그 안의 괄호, 그리고 같은 레벨의 괄호끼리는 왼쪽에서 오른쪽으로 가면서 캡처그룹이 나타남을 알 수 있습니다. 

regex: (a(bc)+dd)+
input: abcbcddabc
찾은 문자열  "abcbcdd" (0, 7)
	(abcbcdd)  (bc)  
input: abcbcbcddabcdd
찾은 문자열  "abcbcbcddabcdd" (0, 14)
	(abcdd)  (bc)  
input: 

위의 예는 캡처그룹 부분에 반복 한정자가 있는 경우 캡처그룹에 인식된 문자열이 어느 것인지 보여줍니다. (bc)+에 의해 bc가 반복될 수 있는 패턴인데, 여기서 캡처그룹에 의해 출력되는 것은 제일 마지막에 매치된 것 한 개만 보여집니다. 역시 두번째 입력문장에 대해서도 전체 매치된 문자열 안에 a(bc)+dd로 매치되는 부분이 두 번 나타나지만 캡처 그룹에서는 마지막에 매치된 것만 보여짐을 알 수 있습니다. 다음 글에서 자바의 Matcher클래스를 살펴보면 분명해 지는데, 자바의 매치 객체는 캡처 그룹에 대해 한 개만 돌려주므로 마지막 것만 확인할 수 있습니다. 위 예에서는 제일 바깥의 +를 없애면 따로따로 매치되는 것을 확인할 수 있겠지요?

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함