JAVA

JAVA 정규식 표현과 정규식

superbono 2022. 2. 23. 18:00

* 정규식이란? 

정규식(regular expression: regex)은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. 

* JAVA 정규식의 사용

정규식은 java.util.regex의 Pattern 과 Matcher 클래스를 주로 이용한다. 

Pattern은 말 그대로 어떤 문자열에서 찾을 패턴을 뜻한다. 

문자열(String)의 정규식은 먼저 Pattern 인스턴스로 컴파일 되어야 한다. 그런 다음 Matcher를 이용, 일치하는 개체를 만들 수 있다. 

일반적인 호출 순서는 다음과 같다. 

 Pattern p = Pattern.compile("a*b"); // a와 b 사이에 문자가 있을 수도 없을 수도?
 
 Matcher m = p.matcher("aaaaab"); 
 Matcher m2 = p.matcher("ab"); 
 Matcher m3 = p.matcher("acb"); 
 
 boolean b = m.matches(); // 매치
 boolean b2 = m2.matches(); // 매치
 boolean b3 = m3.matches(); // 매치

 

또한 matches 메소드를 이용하여 패턴 매칭을 시킬 수도 있는데, 이는 정규식을 한번만 사용할 때 사용한다. 

boolean b = Pattern.matches("a*b", "aaaaab"); // true

matches()는 boolean 타입을 리턴한다.

 

* 정규식의 메타문자들과 그룹

메타 문자들

우선 \가 붙는 문자는 특수문자(명령어?)임을 나타낸다. 

^ : 문자열의 시작을 나타낸다. [] 괄호 안에 쓰이는 경우라면 뒤의 패턴에 일치하지 않기를 나타낸다.

  • "^password=": password:password 에는 매칭되지 않고, password=password에는 매칭된다.
  • "ab[^0-9]": "ab" 뒤에 숫자가 아니어야 매칭된다. ab22: 매칭 안됨 abc: 매칭 됨 

$ : 문자열의 끝 표현

  • ERROR$: 문자열이 ERROR로 끝나는 경우에만 매칭된다.

\b : 단어의 경계. 문자열의 시작과 끝, 공백, 개행, 탭, 콤마, 구두점, 대시문자 등이 올 수 있다. 

  • "\bapple\b" : This is an apple 에는 매칭 되나, This is an pineapple에는 매칭되지 않는다.

\B : \b의 반대

  • \bapple\b" : This is an apple 에는 매칭 되지 않으나, This is an pineapple에는 매칭된다.

\s : 공백 문자 및 탭 문자에 매치한다.


\S : 공백 문자가 아닌 한 글자에 매치한다.

\d : 숫자에 매치한다. [0-9]와 같다.

\D : 숫자가 아닌 문자에 매치한다. [^0-9]와 같다.

\w : 단어를 만들 수 있는 글자. 알파벳 대소문자, 숫자, 언더스코어를 포함한다. [A-Za-z0-9_] 와 같다.

\W : \w에 포함되지 않는 문자들

\n : 개행문자. \r은 캐리지 리턴이다.

\ : 이스케이프용 문자. 정규식 상의 특별한 의미가 있는 문자들을 문자 그대로 쓸 때 앞에 붙인다. \^ 라고 쓰면 “^” 문자 그대로를 가리킨다.

. : 아무 문자 1개에 대응된다. 공백 역시 문자 1개로 취급된다.

| : or의 연산을 한다. 

 

그룹

( ( A ) ( B ( C ) ) )에는 4가지 그룹이 있다. 

group 1: ( ( A ) ( B ( C ) ) )

group 2: ( A )

group 3: ( B ( C ) ) 

group 4: ( C) 

그룹 0는 언제나 전체 문자열 중에서 패턴이 매칭된 문자열 부분이다.

따라서 매칭된 전체 문자열이 아니라 일부 그룹을 보고싶으면 group(1) 부터 보면 좋다.

그룹의 수는 당연히 표현식마다 달라질 수 있다. 

어떤 표현식이 매칭된 문자열의 그룹의 수를 확인하려면 Matcher의 groupCount() 메소드를 사용하면 알 수 있다. 

각각의 문자열 그룹을 확인하기 위해선, groupCount() 만큼 for 문을 돌면서 group을 출력하도록 하는 방법 등이 있다. 

* 예시

ex1)

  • This is a simple question.
  • This is a complicated question.
  • This is a serious question.

과 같이 simple, complicated, serious 를 stupid 라는 단어로 모두 바꾸고 싶다고 하면 정규식을 어떻게 작성하면 될까?

 

public class Example {
    public static void main(String[] args) {
        final String regex = "This is a (.*) question.";
         String string = "This is a simple question.\n"
                + "This is a complicated question.\n"
                + "This is a serious question.\n";

        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            string = string.replace(matcher.group(1), "stupid");
        }
        System.out.println(string);
    }
}

 

ex2)

  • userId=superbono&password=qwerty111&email=email@co.kr
  • email=email2@co.kr&userId=superbono&password=qwerty111
  • password=qwerty111&userId=superbono&email=email@co.kr

 

이렇게 입력이 주어질 때, "password=*****"이렇게 password를 가리고 싶다면 어떻게 해야할까?

더보기

password=(.*?)&|password=(.*?)$

 

* 정규식 공부하기 좋은 사이트 

https://regex101.com/

 

regex101: build, test, and debug regex

Regular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java. Features a regex quiz & library.

regex101.com

정규식 사이트는 여러 곳이 있지만 개인적으로는 이 곳이 제일 좋다.

우선 직관적인 인터페이스와 왼쪽의 code generator를 누르면 작성하려는 언어에 맞게 간단한 예시 코드도 작성해준다. match 되는 그룹에 대해서도 직관적으로 알 수 있어서 애용하고 있다.

저장을 하면 다른 사람들과 공유할 수도 있어, 막혔을 때 저장한 뒤 링크를 보내 누군가에게 물어보기도 편하다. 

 

참고 - https://soooprmx.com/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EA%B8%B0%EC%B4%88-%EB%AC%B8%EB%B2%95/

 

정규표현식의 개념과 패턴 사용법 총정리 · Wireframe

정규 표현식은 텍스트 내에서 특정한 규칙에 따른 문자열이 나타나는 범위를 검색하는 기법으로 텍스트를 다룰 때 널리 사용되며, 특히 텍스트 편집기에서 찾기/바꾸기와 관련해서 정규식을 어

soooprmx.com

https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

 

Pattern (Java Platform SE 7 )

Enables canonical equivalence. When this flag is specified then two characters will be considered to match if, and only if, their full canonical decompositions match. The expression "a\u030A", for example, will match the string "\u00E5" when this flag is s

docs.oracle.com

'JAVA' 카테고리의 다른 글

JVM의 메모리 구조  (1) 2022.07.13
if-else 과 switch 어느 것이 효율적일까?  (0) 2022.02.25
Exception (예외)  (0) 2022.02.13
IntelliJ 단축키 설정  (0) 2021.11.30
Call By Value / Call By Reference  (0) 2021.08.14