Post

Java 정규식에서 subgroup 값 가져오기

Facebook 스프링사용자 모임에 질문이 올라왔다. 아래 코드가 의도와 다른 결과를 뱉는다는 질문이다.

웹에서 정규식을 테스트할수 있는 사이트인 regex101 에서는 정상 작동한다는 말까지 첨부하셧다

1
2
3
4
5
6
7
8
private static final Pattern SIDO_PATTERN = Pattern.compile(
          "(?<sido>\n" +
          "    ([가-힣]+도)|\n" +
          "    ([가-힣]+(특별시|광역시|자치시|자치도))|\n" +
          "    (충북|충남|경북|경남|전북|전남|강원|경기|제주|서울|부산|대구|대전|광주|인천|울산|세종|제주)\n" +
          ")\\s");
SIDO_PATTERN.matcher("서울특별시 강남구 대치동 890-12").matches(); // false
SIDO_PATTERN.matcher("서울특별시 강남구 대치동 890-12").group("sido"); // Match not found

Image

보통 이런경우면 언어마다 미묘하게 다른 정규식 문법의 문제인데… 이번 케이스는 그런것과 좀 다른 특이한 케이스라 혹시 궁금하실분이 있을가봐 정리해둔다

  1. 문제1. 정규식 패턴에 임의로 \n을 넣으면 안된다.
    • 당연하다면 당연하지만 정규식 패턴에 \n이 들어가 있으면 해당 값도 패턴의 일부로 인식된다. 코드 복붙하다 들어간 것 같은데 정확히 넣었어야 했다
  2. 문제2. 자바는 Matching 체크와, SubMatching(용어 맞나?)이 구별되어있다
    • matches를 호출하였는데 다른 언어와 다르게 java는 패턴을 한번 먹인다고 모든 작업이 끝나질 않는다. matches는 전체 패턴이 매칭되었는지를 체크하는 함수고, 특정 그룹을 갖고오고 싶다면 lookingAt 을 호출하여 subgroup 의 파싱을 해 줘야 그 다음으로 group 함수를 사용할 수 있게 된다

수정한 코드는 다음과 같다

1
2
3
4
5
6
7
8
9
10
public class TestClass {
    public static void main(String[] args) {
        var matcher = SIDO_PATTERN.matcher("서울특별시 강남구 대치동 890-12");
        matcher.lookingAt();
        System.out.println(matcher.group("sido"));
    }

    private static final Pattern SIDO_PATTERN = Pattern.compile(
            "(?<sido>([가-힣]+도)|([가-힣]+(특별시|광역시|자치시|자치도))|(충북|충남|경북|경남|전북|전남|강원|경기|제주|서울|부산|대구|대전|광주|인천|울산|세종|제주)\\s)");
}

결과

Image

This post is licensed under CC BY 4.0 by the author.