
들어가며
프로그래밍 언어를 배우다보면 정규 표현식(Regular Expression)이라는 목차를 접하게 됩니다. 정규 표현식은 텍스트에서 특정한 패턴을 검색하거나 조작할 때 사용되는 규칙입니다. 코딩 테스트와 웹 개발 시 종종 쓰이기 때문에 정규 표현식에 대해 꼭 알고 있어야합니다.
정규 표현식에 대해선 이미 숙지하고 있다는 가정하에 자바에서 regex 패키지의 정규 표현식 관련 클래스를 활용하는 방법을 다뤄보겠습니다.
regex package

regex 패키지에서 Matcher와 Pattern 클래스가 존재하는 것을 볼 수 있습니다. 각각의 역할은 다음과 같습니다.
- Pattern : 정규식을 정의하고 컴파일하는 클래스입니다.
- Matcher : 컴파일된 정규 표현식을 사용하여 입력 문자열에서 패턴을 검색하고 매칭 작업을 수행하는 클래스입니다.
Pattern
Pattern은 정규 표현식을 정의하고 컴파일하는 클래스입니다. 문자열 형태의 정규 표현식을 Pattern.compile()이라는 메서드로 컴파일하면 효율적으로 재사용할 수 있습니다.
Pattern 클래스의 메서드를 하나씩 알아보겠습니다.
1. compile
Pattern pattern = Pattern.compile(String regex[, int flag]);
Pattern 객체는 위와 같이 생성할 수 있습니다. compile이라는 정적 메서드에 문자열 형태의 정규 표현식을 전달하면 컴파일하여 JVM이 객체를 생성합니다.
이때 선택적으로 두번째 인자에 정수 형태의 flag를 전달할 수 있는데, flag를 통해 정규 표현식의 동작 방식을 변경할 수 있습니다.
| 플래그 상수 | 설명 |
| Pattern.CASE_INSENSITIVE | 대소문자를 구분하지 않음 |
| Pattern.MULTILINE | 여러 줄 모드 ^와 $가 줄 단위로 작동 |
| Pattern.DOTALL | .이 줄바꿈 문자(\n)도 포함하도록 변경 |
| Pattern.UNICODE_CASE | 유니코드 대소문자 매칭 규칙 적용 |
| Pattern.COMMENTS | 공백과 주석을 무시 |
| Pattern.LITERAL | 정규식을 리터럴로 처리 특수 문자가 메타 문자가 아닌 일반 문자로 처리됨 |
| Pattern.UNICODE_CHARACTER_CLASS | 유니코드 범위를 기반으로 \w, \d, \s 등 동작 변경 |
2. quoto
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String input = "(Hello)!";
String literal = "(Hello)!";
Pattern pattern1 = Pattern.compile(literal);
boolean case1 = pattern1.matcher(input).matches();
System.out.println("Without quote(): " + case1);
Pattern pattern2 = Pattern.compile(Pattern.quote(literal));
boolean case2 = pattern2.matcher(input).matches();
System.out.println("With quote(): " + case2);
}
}
=> 출력
Without quote(): false
With quote(): true
quote는 검색하려는 문자열에 특수 문자가 포함된 경우 자동으로 이스케이프 처리를 해주는 정적 메서드입니다.
위와 같이 input에 literal이 포함되었는지 확인하고 싶을 때 case1처럼 단순히 비교한다면 false가 나옵니다. 하지만 literal을 quote로 한 번 감싸주면 괄호가 아래와 같이 이스케이프 처리되어 true를 출력하게 됩니다.
\(Hello\)!
3. matches
boolean isMatch = Pattern.matches(String regex, String str);
matches는 Pattern 객체를 명시적으로 생성하지 않고 바로 문자열이 정규 표현식과 일치하는지 확인 가능한 정적 메서드입니다. JVM이 내부에서 스스로 정규 표현식을 컴파일해서 1회 비교 후 더이상 참조가 없을 때 가비지 컬렉터에 의해 정리됩니다.
matches는 문자열과 정규 표현식을 비교할 때마다 Pattern 객체를 생성하기 때문에 여러번 matches를 호출하는 것은 비효율적입니다.
4. matcher
Pattern pattern = Pattern.compile(String regex);
Matcher matcher = pattern.matcher(String str);
// 위와 동일
Matcher matcher = Pattern.compile(String regex).matcher(String str);
// 일치 여부 확인
boolean isSame = matcher.matches();
matcher는 Pattern의 인스턴스 메서드로 Matcher 객체를 생성합니다. Matcher는 아래에서 자세히 다루겠습니다.
Matcher
Matcher는 컴파일된 Pattern을 기반으로 입력 문자열에서 패턴을 검색하거나, 매칭된 결과를 탐색, 조작할 수 있도록 도와주는 클래스입니다. Matcher는 Pattern 객체를 기반으로 생성되기 때문에 Pattern 객체의 matcher() 메서드를 호출하여 생성 가능하고 new 키워드를 통해서 Matcher 객체를 만드는 것은 불가능합니다.
Matcher 클래스의 메서드를 알아보겠습니다.
1. matches
boolean isMatch = matcher.matches();
matches는 입력된 문자열의 전체가 정규 표현식과 일치하는지 확인한 뒤에 boolean 값을 반환하는 인스턴스 메서드입니다.
Pattern의 matches VS Matcher의 matches
Pattern 클래스에도 matches라는 정적 메서드가 있고, Matcher 클래스에도 matches라는 인스턴스 메서드가 존재합니다.
Pattern 클래스의 matches는 정규 표현식과 하나라도 일치하는 문자열이 있는지를 확인하는 것이고, Matcher 클래스의 matches는 입력된 문자열 전체가 정규 표현식과 일치하는지 확인하는 메서드입니다.
2. find & group
while (matcher.find()) {
System.out.println(matcher.group());
}
find 메서드는 matches와는 다르게 패턴과 일부 일치하는 문자열을 찾습니다. find를 한 번 호출할 때마다 다음으로 일치하는 문자열이 존재하는지 boolean값을 반환합니다. 즉, 지금까지 발견한 문자열 뒤에도 일치하는 문자열이 존재하는지를 알 수 있습니다.
예를 들어, 문자열 "hello helo hello hello"에서 문자열 hello를 찾으려 할 때 matcher.find()를 3번 호출하면 아래와 같은 결과가 출력됩니다.
true
true
false
group 메서드는 find 메서드로 찾은 일치 문자열을 반환합니다.
3. start & end
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "\\d+";
String input = "abc123xyz456def";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.println("시작 위치: " + matcher.start() + ", 끝 위치: " + matcher.end());
}
}
}
출력 =>
시작 위치: 3, 끝 위치: 6
시작 위치: 9, 끝 위치: 12
start와 end 메서드는 이름에서 알 수 있듯이 현재 find가 가리키는 일치 문자열의 인덱스 시작점과 끝점을 반환합니다.
5. replaceAll
public class Main {
public static void main(String[] args) {
String input = "Hello, World! Hello, Java!";
String result = input.replaceAll("Hello", "Hi");
System.out.println(result);
}
}
출력 => Hi, World! Hi, Java!
replaceAll 메서드는 패턴과 일치하는 문자열을 2번째 인자로 전달된 문자열로 교체하는 메서드입니다. replaceAll은 String 객체를 반환합니다.
Pattern과 Matcher의 주요 메서드는 앞선 설명 설명을 통해 충분히 이해하셨을거라 생각합니다. 마지막으로 간단하게 정규 표현식의 문법이 잘못된 경우 발생하는 PatternSyntaxException 예외를 보고 마무리하겠습니다.
PatternSyntaxException
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class Main {
public static void main(String[] args) {
try {
Pattern.compile("(abc");
} catch (PatternSyntaxException e) {
System.out.println("예외 발생: " + e.getMessage());
}
}
}
출력 =>
예외 발생: Unclosed group near index 4
(abc
PatternSyntaxException는 정규 표현식의 문법이 잘못된 경우 compile 과정에서 발생하는 예외입니다. 위의 예시처럼 닫힌 괄호가 없기 때문에 index 4에서 PatternSyntaxException가 발생한 것을 볼 수 있습니다.
.
.
.
마치며
백준의 아래 링크에서 필터링된 문제들을 풀어보면 Pattern과 Matcher를 이해하는데 도움이 될 것 같습니다.
https://www.acmicpc.net/problemset?sort=solvedac_asc&algo=63&algo_if=and
'Java' 카테고리의 다른 글
| Java 객관식 개념 문제(30문항) v1.1 (3) | 2025.02.02 |
|---|---|
| [Java] Collections Framework간 변환 총정리 - List, Set, Map, Queue (1) | 2024.12.03 |
| [Java] BufferedReader 사용법과 자료구조 총정리 (1) | 2024.10.18 |
| [Java] compare 메서드에서 overflow가 발생하지 않는 이유 (0) | 2024.10.14 |
| [Java] toString과 String.valueOf 메서드 차이 (3) | 2024.10.14 |