[Java] Pattern, Matcher로 정규식 매칭 문자열 자르기
정규식을 전문적으로 다루는 클래스 두 가지( Pattern
, Matcher
)를 활용해 손쉽게 문자열 패턴 매칭을 수행할 수 있다.
다음 코드를 보며 기본적인 사용법을 알아보자.
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaaaab");
boolean result = matcher.matches();
- 먼저정규식을 인자로 Pattern 클래스의 static 메소드
compile(String regex)
을 호출해 패턴을 만든다. - 만들어진 Pattern 객체로 매칭해 볼 문자열을 인자로 전달해
matcher(String input)
메소드를 호출해 Matcher 객체를 만든다. - 위의 1, 2 작업이 끝나면 Matcher 객체로
matches()
메소드를 호출해 매칭 유무를 불리언 값으로 받는다.
매칭해 볼 문자열 내에 정규식 표현이 여러 번 등장할 수 있다. 예를 들어, [프로그래머스] 17682. 다트 게임 문제를 정규식 패턴으로 표현하면 다음과 같다.
String regex = "([0-9]*)([SDT])([*#]?)";
정규식 테스트 사이트에서 문자열 1S2D*3T
는 위에 작성된 정규식 ([0-9]*)([SDT])([*#)?)
에 세 번 매칭됨을 아래 사진에서 확인할 수 있다.
세 번 매칭되니 matches() 메소드가 true 를 반환할 것이라고 예상하고 아래 코드를 작성해보지만, 그 값을 찍어보면 false 가 나오는 걸 확인할 수 있다. matches()
메소드는 패턴이 전체 문자열과 일치할 경우 true 를 반환하기 때문이다.
Pattern pattern = Pattern.compile("([0-9]*)([SDT])([*#]?)");
Matcher matcher = pattern.matcher("1S2D*3T");
System.out.println(matcher.matches()); // false
matcher = pattern.matcher("1S");
System.out.println(matcher.matches()); // true
matcher = pattern.matcher("2D*");
System.out.println(matcher.matches()); // true
matcher = pattern.matcher("3T");
System.out.println(matcher.matches()); // true
그럼 위 문제처럼 전체 문자열 안에 패턴과 일치하는 부분 문자열이 여러 번 등장하는 경우, 어떻게 매칭 처리를 해야할까?
Matcher 클래스에는 find()
메소드가 있다. 이 메소드는 전체 문자열 내에서 패턴에 일치하는 부분 문자열만을 가지고 매칭 일치 여부를 판단한다. 따라서 find() 메소드를 사용하면, 전체 문자열 1S2D*3T
는 1S
, 2D*
, 3T
총 세 번의 매칭에 성공하게 된다.
Matcher 클래스에는 group()
메소드를 통해 패턴 내 각 그룹을 접근할 수 있다. 정규식 내부에서 중괄호로 감싸진 부분은 하나의 그룹을 뜻한다. 정규식 ([0-9]*)([SDT])([*#]?)
은 아래와 같이 세 개의 그룹을 갖는다.
- ([0-9]*)
- ([SDT])
- ([*#]?)
Matcher 객체를 이용해 find() 메소드를 호출해 패턴에 맞는 각 부분 문자열을 받아온 뒤 group()
메소드를 호출하면, 매칭된 부분 문자열을 반환한다.
matcher.find();
System.out.println(matcher.group()); // 1S
matcher.find();
System.out.println(matcher.group()); // 2D*
matcher.find();
System.out.println(matcher.group()); // 3T
또한 인자에 인덱스를 주어 패턴 내 각 그룹에 접근 가능하다.
matcher.find();
System.out.println(matcher.group()); // 2D*
System.out.println(matcher.group(1)); // 2
System.out.println(matcher.group(2)); // D
System.out.println(matcher.group(3)); // *
추가로, 패턴을 생성할 때 ?<name>
키워드를 사용해 그룹 명을 붙일 수 있다. 이후에는 matcher.group("name")
과 같이 인덱스 대신 이름으로 해당 그룹을 접근할 수 있게 된다.
댓글남기기