자바에서는 정규식을 활용해 문자열을 검증, 탐색을 돕는 Pattern, Matcher 클래스를 제공해준다.
다음에도 쉽게 활용할 수 있도록 정리하려고 한다.
👨🏫 클래스 분석
Pattern
정규 표현식이 컴파일된 클래스. 정규 표현식에 대상 문자열을 검증하거나, 활용하기 위해 사용되는 클래스이다.
주요 메소드
static Pattern compile(String regex) | 주어진 정규식을 갖는 패턴을 생성 |
String pattern() | 컴파일된 정규 표현식을 반환 |
Matcher matcher(CharSequence input) | 패턴에 매칭할 문자열을 입력해 Matcher를 생성 |
static boolean matches(String regex, CharSequence input) | 정규식과 문자열이 일치하는지 확인 |
String[] split(CharSequence input) String[] split(CharSequence input, int limit) |
패턴이 일치하는 항목을 중심으로 input을 분할 limit - 1의 횟수만큼 패턴 일치를 시켜 문자열을 자름(문자열이 limit개 생성) 만약 0이하라면 최대한 많이 적용 |
Matcher
Pattern클래스를 받아 대상 문자열과 패턴이 일치하는 부분을 찾거나 전체 일치 여부 등을 판별하기 위해 사용된다.
주요 메소드
Pattern pattern() | matcher가 해석한 패턴을 반환 |
Matcher usePattern(Pattern newPattern) | matcher가 사용할 Pattern을 변경 |
Matcher reset(CharSequence input) | matcher가 분석할 문자열을 변경 |
int start() | 매칭하는 문자열의 시작 인덱스를 반환 |
int start(int group) | 매칭 문자열 중 group번째 문자열의 시작 인덱스를 반환 0은 그룹의 전체 패턴을 의미 start(0) = start() |
int start(String name) | 매칭 문자열 중 해당 name을 지정한 그룹의 시작 인덱스를 반환 |
int end() | 일치하는 문자열의 마지막 문자열 이후 인덱스를 반환 |
int end(int group) | 매칭 문자열 중 group번째 그룹의 마지막 문자열 이후(+1) 인덱스를 반환 0은 그룹의 전체 패턴을 의미 end(0) = end() |
int end(String name) | 매칭 문자열 중 해당 name을 지정한 그룹의 마지막 문자열 이후(+1) 인덱스를 반환 |
String group() | 매치와 일치하는 문자열을 반환 |
String group(int group) | 매칭되는 문자열 중 group번째 그룹의 문자열 반환 0은 그룹의 전체 패턴을 의미 group(0) = group() |
String group(String name) | 매칭되는 문자열 중 해당 name을 지정한 그룹의 문자열 반환 |
int groupCount() | 패턴 내에 그룹핑한 개수를 반환(패턴에 있는 괄호 개수) |
boolean matches() | 패턴에 전체 문자열이 일치한 경우 true를 반환 |
boolean find() | 패턴이 일치하는 다음 문자열을 찾는다 다음 문자열이 있다면 true |
boolean find(int start) | start 인덱스 이후부터 패턴에 일치하는 문자열을 찾는다 |
String replaceAll(String replacement) | 패턴과 일치하는 모든 문자열을 지정된 replacement로 변경 |
👩💻 이해 & 활용하기
1️⃣ 생성하기, 정규식 일치여부 판별하기
Pattern 클래스는 Pattern.compile(regex)를 통해 생성할 수 있고, 컴파일된 패턴을 사용하는 Matcher는 만들어진 객체에 matcher(input) 메소드를 사용해 생성한다.
String regex = "^[a-zA-Z]$"; // 영문자만 존재하는가?
String input = "Test String";
System.out.println(Pattern.matches(regex, input)); // false
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
System.out.println(matcher.matches());// false
제일 기본적으로 사용할 수 있는 메소드는 Pattern.matches(regex, input)
와 Matcher.matches()
이다. 두 메소드 모두 주어진 문자열이 패턴에 맞는지 판별하는 메소드이다. 주어진 문자열에서는 공백이 포함되었기 때문에 false가 반환된다.
2️⃣ Grouping
예시) 프로그래머스 - 2018 KAKAO BLIND RECRUITMENT [1차] 다트게임 사용(🔗 링크)
Matcher에 주어진 input 문자열을 패턴에 맞는지 확인하거나 패턴과 일치하는 문자열을 반복해 추출할 수 있는데, 이때 find()
메소드와 group()
메소드가 사용된다. find()
메소드는 패턴이 일치하는 다음 문자열이 존재한다면 true를 반환하기 때문에 while문을 통해 문자열의 끝까지 조회가 가능하다
Pattern pattern = Pattern.compile("([0-9]+)([SDT])([*#]?)");
Matcher matcher = pattern.matcher("1D2S#10S*");
while(matcher.find()){
System.out.println(matcher.group());
}
// 1D
// 2S#
// 10S*
출력을 확인해보면 위와 같이 문자열이 분리되는 것을 알 수 있다. find()를 통해 찾은 문자열에서 start(), end(), group() 메소드를 추가적으로 활용할 수 있다.
패턴의 그룹은 소괄호()를 기준으로 지정되는데 예제의 정규식에서는 위와같이 분리되는 것을 알 수 있다.
while (matcher.find()) {
System.out.println(matcher.group(1) + "/" + matcher.group(2) + "/" + matcher.group(3));
System.out.println(matcher.start(1) + "/" + matcher.start(2) + "/" + matcher.start(3));
System.out.println(matcher.end(1) + "/" + matcher.end(2) + "/" + matcher.end(3));
System.out.println();
}
/* 출력
1/D/
0/1/2
1/2/2
2/S/#
2/3/4
3/4/5
10/S/*
5/7/8
7/8/9
*/
이를 통해 메소드를 다시 한 번 이해 해보면,
group(int i)
는 i번째 그룹의 문자열,
start(int i)
는 i번째 그룹의 문자열의 시작 인덱스,
end(int t)
는 i번째 그룹의 문자열의 종료 인덱스 + 1의 값을 반환하는 것을 알 수 있다!
만약 그룹을 숫자로 매번 사용하기 어렵다면 각 그룹마다 이름을 붙일 수 있다. 각 그룹에 ?<'name'>
을 통해 이름을 지정하면 group(), start(), end() 등의 함수에서 순서를 외울 필요 없이 이름으로 접근이 가능해진다.
Pattern pattern = Pattern.compile("(?<score>[0-9]+)(?<bonus>[SDT])(?<option>[*#]?)");
Matcher matcher = pattern.matcher("1D2S#10S*");
while(matcher.find()){
System.out.println(matcher.group("score"));
}
// 1
// 2
// 10
📚 Reference
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html
https://docs.oracle.com/javase/9/docs/api/java/util/regex/Pattern.html
'Programming > Java' 카테고리의 다른 글
[Java] 어노테이션(Annotation) (0) | 2021.03.01 |
---|---|
[Java] Java란? Java의 특징 (0) | 2021.02.16 |
[Java] 정규식 문법 정리(Regex) (2) | 2021.01.20 |
[Java] JVM, JDK, JRE의 차이 (0) | 2021.01.01 |
[Java] Iterable과 Iterator (0) | 2020.12.13 |