IT/언어

[Java] 정규표현

개발자 두더지 2023. 7. 26. 22:02
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 

Java의 정규표현


 Java에는 정규표현에 관련된 기능을 구현하기 위한 패키지 java.util.regex가 있으며, 그 안에 Pattern 클래스와 Matcher 클래스가 있다.

 Pattern 클래스는 정규표현의 "패턴"을 나타내고, Mather 클래스는 검색하고 싶은 문자열과 정규표현과의 "매칭"을 실행한다.

 

Pattern 클래스

 Pattern 클래스는 정규표현의 "패턴"을 나타내는 클래스이다. Java에서 정규표현을 사용할 때는 java.util.regex.Pattern클래스의 compile메소드를 호출하여, 정규표현을 컴파일한다. 

 정규표현의 구문 규칙에 따르지 않은 경우 예외를 throw한다. 

 Pattern.compile 메소드의 상세 내용이다.

public static Pattern compile(String regex)
  • 패턴 : regex - 컴파일된 표현
  • 반환값 : 패턴에 커파일할 지정된 정규표현
  • 예외 : PatternSyntaxException - 표현 구문이 무효인 경우

 

Matcher 클래스

 정규표현의 매칭은 Pattern.matcher 메소드에 대상 문자열을 전달하여, Matcher 클래스의 인스턴스를 획득하여 매칭하고 있는지를 조사한다.

 메소드의 상세는 다음과 같다.

public Matcher matcher(CharSequence input)

 지정된 입력과 그 패턴에 매칭되는 정규표현 엔진을 만든다.

  • 파라미터 : input - 매치된 문자 시퀀스
  • 반환값 : 그 패턴의 새로운 정규표현 엔진

 

 

정규표현의 사용법


 정규표현의 사용법을 샘플코드를 이용해 설명하고자한다.

 

Pattern오브젝트 만들기

 정규표현의 Pattern 오브젝트를 만드는데에는 Pattern.compile 메소드의 인수에 정규 표현 패턴을 지정한다. 그럼 Pattern 클래스의 샘플 코드를 살펴보자.

 다음의 예는 우편 번호 형식에 매치하는 정규표현을 Pattern.compile 메소드로 지정하여, pattern인스턴스를 만드는 코드이다.

import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("^[0-9]{3}-[0-9]{4}$"); 
    }
}

 

matches 메소드를 사용하기

Pattern 오브젝트를 생성하면 다음은 문자열과 정규표현을 매칭한다. 매칭하기 위해서는 Pattern.matcher 메소드로 얻어진 matcher 인스턴스의 find 메소드로 조사한다.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class App {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("^[0-9]{3}-[0-9]{4}$");
        String postno = "100-0001";
        Matcher matcher = pattern.matcher(postno);
        if (matcher.find()) {
            System.out.println("정규표현에 매칭됐습니다.");
        } else {
            System.out.println("매칭되지 않았습니다.");
        } 
    }    
}

 

 

Mater 클래스의 group 메소드


public String group()

 정규표현에 일치하는 여러 개의 값(문자열)을 반환하는 메소드이다. 

package test1;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test1 {
    public static void main(String[] args) {

        String a = "ABCABC";
    	
    	Pattern p = Pattern.compile("BC");
    	Matcher m = p.matcher(a);

        while (m.find()) {
            System.out.println(m.group()); // BC BC
        }
    }
}

 while(m.find())로 find 메소드가 false가 될 때까지 매치를 반복하여, 문자열의 시작 위치(start), 종료 위치(end), 매치된 문자열(group)을 획득한다. 인덱스등으로 매칭된 각 문자열 요소를 획득할 수 있다. 다음과 같이 말이다.

  • group[0] : 매칭된 문자열 전체
  • group[1] : 서브 매치 문자열 첫 번째 요소

 

 

매칭 동작 제어


 매칭 클래스로 Pattern 클래스를 인스턴스화할 때의 동작을 변경할 수 있다.

 

CASE_INSENSITIVE

 대문자 소문자 구분하지 않기

import java.util.*;
import java.util.regex.Pattern;

public class Main {
  public static void main(String[] args) {
    var str = "업무용은 neko@example.com이다. 개인용은 NEKO@example.com이다.";
    var ptn = Pattern.compile("[a-z0-9.!#$%&'*+/=?^_{|}~-]+@[a-z0-9-]+(\\.[a-z0-9-]+)*", Pattern.CASE_INSENSITIVE);
    var match = ptn.matcher(str);
    while (match.find()) {
      System.out.println(match.group());
    }
  }
}

 

MULTILINE

  • ^, $의 동작 변경
  • ^은 맨 앞뿐만 아니라 개행 후의 숫자도 매치
  • $의 행 끝에도 매치
import java.util.*;
import java.util.regex.Pattern;

public class Main {
  public static void main(String[] args) {
    var str = "1학년이 되면 친구 \n100명 만들 수 있을까\n";
    // var ptn = Pattern.compile("^\\d*");
    var ptn = Pattern.compile("^\\d*", Pattern.MULTILINE);
    var match = ptn.matcher(str);
    while (match.find()) {
      System.out.println(match.group()); //1 100
    }
  }
}

 

DOTALL

  • .의 동작 변경
  • 개행(\n)도 포함한 모든 문자열에 매치
  • 문자열을 단일행으로 매치할 수 있다.
import java.util.*;
import java.util.regex.Pattern;

public class Main {
  public static void main(String[] args) {
    var str = "보고싶었어\n보고싶었어\n보고싶었어\nYES";
    // var ptn = Pattern.compile("^.+");
    var ptn = Pattern.compile("^.+", Pattern.DOTALL);
    var match = ptn.matcher(str);
    while (match.find()) {
      System.out.println(match.group());
      //보고싶었어
      //보고싶었어
      //보고싶었어
      //YES
    }
  }
}

 

 

자주 사용하는 정규표현 목록


정규표현 의미 표기 예시 합치하는 문자열의 예시
* 0회 이상의 반복 a* ␣,a,aa,aaa
+ 1회 이상의 반복 ab+ ab,abab,ababab,abb
? 0회 or 1회의 반복 ba? b,ba
^ 직후의 문자가 행의 선두에 있는 경우 매치 ^Java Java Programming
$ 직전의 문자열이 행의 맨끝에 있는 경우 매치 Programing$ Java Programming
. 개행 이외의 임의의 한 문자에 매치 . A,1
| OR조건으로 사용 0(7|8|9)0 070,080,090
{N} N회 반복 (abc){3} abcabcabc
{M,N} M회 이상 N회 이하의 반복 a{2,4} aa,aaa,aaaa
[A-Z] 영어 대문자 A-Z 사이의 임의의 한 문자에 매치 a[A-Z] aA,aB,aX,aY
[a-z] 영어 소문자 a-z사이의 임의의 한 문자에 매치 b[a-z] ba,bc,bx,by,bz
[0-9] 숫자 0-9사이의 임의의 한 문자에 매치 c[0-9] c1,c9,c0

 정규표현에서는 *, ?, {}, [] 등 몇 가지 문자를 특수한 의미로 이용한다. 이러한 특수 문자를 정규표현의 패턴으로 지정하고 싶은 경우는 백슬래시(\) 를 사용하여 무표화(이스케이프)시키면 된다.


참고자료

https://camp.trainocate.co.jp/magazine/java-regular-expressions/

https://itsakura.com/java-matcher-group

https://qiita.com/suema0331/items/5dde9f91671100a83905

728x90