소유 수량자란 무엇인가?
탐욕적 수량자(Greedy Quantifier)는 정규식에서 기본값으로 사용되는 수량자입니다. 탐욕적 수량자는 입력 문자열에서 가능한 한 가장 긴 매칭을 시도하며, 매칭에 실패하면 마지막 문자 하나를 되돌려 놓는 백트래킹(backtracking) 과정을 거친 후 다시 매칭을 시도합니다.
소유 수량자(Possessive Quantifier)는 탐욕적 수량자와 동작 방식이 유사하지만 결정적인 차이가 있습니다. 소유 수량자 역시 처음에 가능한 한 많은 문자를 매칭하려고 시도하지만, 매칭에 실패했을 때 탐욕적 수량자처럼 백트래킹을 수행하지 않습니다. 즉, 한 번 문자를 점유하면 그 문자를 포기하지 않기 때문에 '소유(possessive)'라는 이름이 붙었습니다.
이러한 특성 덕분에 소유 수량자는 불필요한 백트래킹을 방지하여 매칭 속도를 크게 향상시킬 수 있으며, 심각한 성능 저하를 유발하는 재앙적 백트래킹(catastrophic backtracking) 문제를 예방하는 데에도 유용합니다.
소유 수량자 표기법
탐욕적 수량자 뒤에 +를 붙이면 해당 수량자는 소유 수량자로 변환됩니다. 다음은 Java에서 사용할 수 있는 대표적인 소유 수량자 목록입니다.
| 수량자 | 설명 |
|---|---|
| re*+ | 0번 이상 일치합니다. |
| re?+ | 0번 또는 1번 일치합니다. |
| re++ | 1번 이상 일치합니다. |
| re{n}+ | 정확히 n번 일치합니다. |
| re{n, m}+ | 최소 n번, 최대 m번 일치합니다. |
예제 코드
다음 예제는 소유 수량자 [0-9]++를 사용하여 입력 문자열에서 연속된 숫자를 추출하는 Java 프로그램입니다.
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter input text: ");
String input = sc.nextLine();
String regex = "[0-9]++";
// 패턴 객체 생성
Pattern pattern = Pattern.compile(regex);
// 컴파일된 패턴을 문자열과 매칭
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.print(matcher.group());
System.out.println();
}
}
}
실행 결과
입력값으로 45678을 넣으면 소유 수량자 ++가 연속된 숫자 전체를 한 번에 매칭하여 아래와 같은 결과를 출력합니다.
Enter input text: 45678 45678