Dico

[Java] 정규식

정규식 Regular Expression

package java.util.regex

java.lang. Object

     (classes)

        ↳  java.util.regex. Matcher (implements java.util.regex. MatchResult)

        ↳  java.util.regex. Pattern (implements java.io. Serializable)

     (Exceptions)

        ↳  java.lang. Throwable (implements java.io. Serializable)

            ↳  java.lang. Exception

                ↳  java.lang. RuntimeException

                    ↳  java.lang. IllegalArgumentException

                        ↳  java.util.regex. PatternSyntaxException

     (Interfaces)

        ↳  java.util.regex. MatchResult

정규식

텍스트 데이터 중에서 원하는 조건(패턴, pattern)과 일치하는 문자열을 찾아내기 위해 사용하는 것.

미리 정의된 기호와 문자를 이용해서 작성한 문자열.

  • Pattern

     정규식을 정의하는 데 사용한다.

public final class Pattern implements java.io.Serializable {}
  • Matcher

     정규식(패턴)을 데이터와 비교하는 역할.

public final class Matcher implements MatchResult {}

정규식을 정의하고 데이터를 비교하는 과정

1. 정규식 정의 - Pattern 인스턴스 얻기

    Pattern 클래스의 static Pattern compile(String regex)을 호출하여 정규식을 매개변수로 전달한다.

Pattern p = Pattern.compile("a[a-z]*");

2. 정규식으로 비교할 대상 정의 - Matcher 인스턴스 얻기

    Pattern 클래스의 Matcher matcher(CharSequence input)을 호출하여 비교 대상을 매개변수로 전달한다.

String data[] = {"apple", "ago", "aA", "a0", "a#", "a.", "love", "a", "alpha",
        "avenge", "field", "az", "simulation", "animal", "java", "kotlin", "data"};

for (int i = 0; i < data.length; i++) {
    Matcher m = p.matcher(data[i]);
}

3. 정규식에 부합하는 지 확인

    Matcher 인스턴스에 boolean matches() 호출

for (int i = 0; i < data.length; i++) {
    Matcher m = p.matcher(data[i]);
    if(m.matches());
        Log.d("TAG_", data[i]);         // apple  ago  a  alpha  avenge  az  animal
}

정규식 패턴

  • a[a-z]*

    a로 시작하는 영단어. 소문자.

Pattern p = Pattern.compile("a[a-z]*");
// apple,ago,a,alpha,avenge,az,animal
  • a[a-z]

    a로 시작하는 두 자리 영단어. 소문자.

Pattern p = Pattern.compile("a[a-z]");
// az
  • a[a-zA-Z]

    a로 시작하는 두 자리 영단어. 대소문자 구분 없음.

Pattern p = Pattern.compile("a[a-zA-Z]");
// aA,az
  • a[a-zA-Z0-9] 또는 a\w

    a로 시작하고 숫자와 영어로 조합된 두 글자

Pattern p = Pattern.compile("a\\w");
// aA,a0,az
  • .*

    모든 문자열

Pattern p = Pattern.compile(".*");
// apple,ago,aA,a0,a#,a.,love,a,alpha,avenge,field,az,simulation,animal,java,kotlin,data
  • a.

    a로 시작하는 두 자리 문자열.

Pattern p = Pattern.compile("a.");
// aA,a0,a#,a.,az
  • a.*

    a로 시작하는 모든 문자열. 기호 포함.

Pattern p = Pattern.compile("a.*");
// apple,ago,aA,a0,a#,a.,a,alpha,avenge,az,animal
  • a\.

    a.와 일치하는 문자열.

Pattern p = Pattern.compile("a\\.");
// a.
  • a\d 또는 a[0-9]

    a와 숫자로 구성된 두 자리 문자열.

Pattern p = Pattern.compile("a\\d");
// a0
  • a.*e

    a로 시작하고 e로 끝나는 모든 문자열.

Pattern p = Pattern.compile("a.*e");
// apple,avenge
  • [l|f].* 또는 [lf].* 또는 [l-f].*

    l 또는 f로 시작하는 문자열.

Pattern p = Pattern.compile("[l|f].*");
// love,field
  • [^l|f].* 또는 [^lf].* 또는 [^l-f].*

    l 또는 f로 시작하지 않는 문자열.

Pattern p = Pattern.compile("[^lf].*");
// apple,ago,aA,a0,a#,a.,a,alpha,avenge,az,simulation,animal,java,kotlin,data
  • .*n.*

    n을 포함하는 모든 문자열.

    * :  0 또는 그 이상의 문자

Pattern p = Pattern.compile(".*n.*");
// avenge,simulation,animal,kotlin
  • .*n.+

    n을 포함하는 모든 문자열.

    + :  1 또는 그 이상의 문자. 반드시 하나 이상의 문자가 있어야 한다.

    n으로 끝나는 단어는 포함되지 않는다.

Pattern p = Pattern.compile(".*n.+");
// avenge,animal
  • [l|j].{3}

    l 또는 j로 시작하는 네 자리 문자열

Pattern p = Pattern.compile("[l|j].{3}");
//love,java

그룹화

정규식의 일부를 괄호()로 나누어 묶는다.

그룹화된 부분은 group(int i)를 이용해서 나누어 얻을 수 있다.

group()/group(0)은 그룹으로 매칭된 문자열을 전체를 나누지 않은 채로 반환한다.

String source = "PONE: 010-3434-5555, HOME:031-234-8888";
String pattern = "(0\\d{1,2})-(\\d{3,4})-(\\d{4})";

Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(source);

while (m.find()) {
    Log.d("TAG_", m.group());
    Log.d("TAG_", m.group(1) + " / " + m.group(2) + " / " + m.group(3));
}
010-3434-5555
010 / 3434 / 5555
031-234-8888
031 / 234 / 8888

0\\d{1,2} :  0으로 시작하는 최소 2자리 최대 3자리 숫자. 0포함

\\d{3,4} :  최소 3자리 최대 4자리의 숫자

\\d{4} :  4자리의 숫자

Matcher의 boolean find()

주어진 소스 내에서 패턴과 일치하는 부분을 찾아내면 true 반환.

다시 호출하면 이전에 발견한 패턴과 일치하는 부분의 다음부터 다시 패턴 매칭을 시작한다.

  • 정규식와 일치하는 부분을 찾았을 경우 (find() == true)

    int start() :  매칭된 문자열의 시작 위치 반환.

    int end() :  매칭된 문자열의 끝 다음 문자의 위치 반환.

    Matcher appendReplacement(StringBuffer sb, String replacement) :  source 시작부터 원하는 문자열로 치환된 위치까지의 내용을 저장.

    StringBuffer appendTail(StringBuffer sb) :  마지막으로 치환된 이후의 부분을 sb에 덧붙인다.

String source = "The friendship that can cease has never been real.";
String pattern = "friendship";
StringBuffer sb = new StringBuffer();

Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(source);

while (m.find()) {
    Log.d("TAG_", m.start() + " ~ " + m.end());   //  4 ~ 14
    m.appendReplacement(sb, "love");
    Log.d("TAG_", sb + "");                       // The love
}
m.appendTail(sb);

Log.d("TAG_", sb + "");                           // The love that can cease has never been real.

참고 서적: 자바의 정석 3판