Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

예제로 배우는 Java Matcher quoteReplacement(String s) 메서드 완벽 가이드

quoteReplacement() 메서드란?

Java 정규식 처리 시 Matcher 클래스의 appendReplacement() 메서드는 StringBuffer 객체와 대체 문자열(replacement string)을 매개변수로 받아, 입력 데이터를 StringBuffer에 추가하면서 일치된 내용을 대체 문자열로 교체하는 역할을 합니다.

내부적으로 이 메서드는 입력 문자열에서 한 문자씩 읽어 버퍼에 추가하다가, 일치(match)가 발견되면 일치된 부분 대신 대체 문자열을 버퍼에 넣고, 일치한 하위 문자열의 다음 위치부터 계속 진행합니다.

그런데 이 메서드에 대체 문자열을 전달할 때 슬래시(/)나 달러 기호($)가 포함되어 있으면 일반 문자로 취급되지 않고 아래와 같은 예외가 발생합니다.

예제 1 — 특수문자 사용 시 발생하는 오류

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class QuoteReplacement {
    public static void main(String[] args) {
        String str = " <p>This <b>is</b> an <b>example</b> HTML <b>script</b>.</p>";
        // 굵은 글씨(bold) 태그 내용을 찾기 위한 정규식
        String regex = "<b>(\\S+)</b>";
        System.out.println("Input string: \n"+str);
        // Pattern 객체 생성
        Pattern pattern = Pattern.compile(regex);
        // 컴파일된 패턴을 문자열에 적용
        Matcher matcher = pattern.matcher(str);
        // 빈 StringBuffer 생성
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "sampledata$" );
            //Matcher.quoteReplacement("Bo$ld/Data$"));
        }
        matcher.appendTail(sb);
        System.out.println("Contents of the StringBuffer: \n"+ sb.toString() );
    }
}

실행 결과

Input string:
<p>This <b>is</b> an <b>example</b> HTML <b>script</b>.</p>
Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference: group index is missing
    at java.util.regex.Matcher.appendReplacement(Unknown Source)
    at OCTOBER.matcher.QuoteReplacement.main(QuoteReplacement.java:18)

위 실행 결과에서 볼 수 있듯이, 대체 문자열에 $ 기호가 포함되면 Illegal group reference 예외가 발생합니다. 이는 $가 정규식에서 그룹 참조(group reference)를 의미하기 때문입니다.

해결 방법 — quoteReplacement() 메서드 활용

Matcher 클래스의 quoteReplacement() 메서드는 문자열 값을 받아 리터럴(literal) 대체 문자열을 반환합니다. 즉, 주어진 문자열에서 /와 $ 문자가 일반 문자로 취급되며, 반환된 결과는 appendReplacement() 메서드의 매개변수로 안전하게 사용할 수 있습니다.

예제 2 — quoteReplacement() 적용 후 정상 동작

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class QuoteReplacement {
    public static void main(String[] args) {
        String str = "<p>This <b>is</b> an <b>example</b> HTML <b>script</b>.</p>";
        // 굵은 글씨(bold) 태그 내용을 찾기 위한 정규식
        String regex = "<b>(\\S+)</b>";
        System.out.println("Input string: \n"+str);
        // Pattern 객체 생성
        Pattern pattern = Pattern.compile(regex);
        // 컴파일된 패턴을 문자열에 적용
        Matcher matcher = pattern.matcher(str);
        // 빈 StringBuffer 생성
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, Matcher.quoteReplacement("Bo$ld/Data$"));
        }
        matcher.appendTail(sb);
        System.out.println("Contents of the StringBuffer: \n"+ sb.toString() );
    }
}

실행 결과

Input string:
<p>This <b>is</b> an <b>example</b> HTML <b>script</b>.</p>
Contents of the StringBuffer:
<p>This Bo$ld/Data$ an Bo$ld/Data$ HTML Bo$ld/Data$.</p>

Matcher.quoteReplacement()를 적용하자 $와 /가 특수문자가 아닌 일반 문자열로 처리되어, 더 이상 예외 없이 의도한 대로 치환이 완료된 것을 확인할 수 있습니다.

예제 3 — quoteReplacement() 단독 사용

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class QuoteReplacementExample {
    public static void main(String[] args) {
        String input = "This is sample text";
        String regex = "[#]";
        // Pattern 객체 생성
        Pattern pattern = Pattern.compile(regex);
        // 컴파일된 패턴을 문자열에 적용
        Matcher matcher = pattern.matcher(input);
        // 빈 StringBuffer 생성
        String str = Matcher.quoteReplacement("sampledata");
        System.out.println(str);
    }
}

실행 결과

sampledata

정리

appendReplacement() 사용 시 대체 문자열에 $나 / 같은 특수문자가 포함될 가능성이 있다면, 반드시 Matcher.quoteReplacement()로 감싸서 전달하는 것이 안전합니다. 이를 통해 IllegalArgumentException과 같은 런타임 예외를 예방하고, 사용자 입력값을 치환 문자열로 사용할 때도 안정적으로 처리할 수 있습니다.