정규식 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_TEST", 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.*t");
// 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_TEST", m.group());
    Log.d("TAG_TEST", 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_TEST", m.start() + " ~ " + m.end());   //  4 ~ 14
    m.appendReplacement(sb, "love");
    Log.d("TAG_TEST", sb + "");                       // The love
}
m.appendTail(sb);

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




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