정규표현식

문자 제거, 치환, 형식 검사, 간단한 숫자 추출 에 사용

str.matches(regex);                    // 전체 문자열이 regex와 일치하는지 검사
str.replaceAll(regex, replacement);    // regex에 맞는 부분 치환
str.split(regex);                      // regex 기준으로 문자열 분리

자주 쓰는 패턴

Info

"[0-9]"          // 숫자 1개
"[0-9]+"         // 숫자 1개 이상
"[^0-9]"         // 숫자가 아닌 문자
 
"[a-zA-Z]"       // 영문자
"[a-z0-9]"       // 소문자 또는 숫자
"[^a-z0-9]"      // 소문자, 숫자가 아닌 문자
 
"\\s"            // 공백
"\\."            // 문자 그대로의 점(.)
 
"^abc"           // abc로 시작
"abc$"           // abc로 끝
"^abc$"          // 정확히 abc
 
"a+"             // a가 1개 이상
"a*"             // a가 0개 이상
"a?"             // a가 0개 또는 1개
"a{2,}"          // a가 2개 이상
"a{2,5}"         // a가 2개 이상 5개 이하

용례

Info

문자열에서 특정 문자만 남기거나 제거할 때 가장 많이 쓴다.

String s = "a1b2c3";
 
s = s.replaceAll("[^0-9]", "");  // 숫자만 남김: "123"
s = s.replaceAll("[0-9]", "");   // 숫자 제거: "abc"

아이디 정리류 문제:

s = s.toLowerCase();
s = s.replaceAll("[^a-z0-9-_.]", ""); // 허용 문자 외 제거
s = s.replaceAll("\\.{2,}", ".");     // 점 2개 이상 -> 점 1개
s = s.replaceAll("^[.]|[.]$", "");    // 처음 또는 끝의 점 제거

형식 검사:

boolean ok = s.matches("^[a-zA-Z0-9]{8,20}$"); // 영문+숫자 8~20자

숫자 추출:

Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher("a10 b20 c300");
 
while (m.find()) {
    System.out.println(m.group()); // 10, 20, 300
}

그룹화

Info

괄호 ()는 그룹이다.
replaceAll()에서 $1, $2로 그룹 값을 다시 사용할 수 있다.

String str = "apple123";
 
String result = str.replaceAll("(apple)([0-9]+)", "$1 $2");
 
// apple 123

Matcher에서는 group(1)부터 괄호 그룹이다.

Pattern p = Pattern.compile("([가-힣]+)[은는이가] ([0-9]+)개");
Matcher m = p.matcher("사과가 10개 있다");
 
if (m.find()) {
    String name = m.group(1);   // 사과
    String count = m.group(2);  // 10
}

주의점

Warning

이것만 조심하면 된다.

실수주의
matches()부분 일치가 아니라 전체 일치
.아무 문자 1개. 진짜 점은 "\\."
+, *, ?수량자. 문자 그대로 쓰려면 이스케이프 필요
replaceAll()첫 번째 인자는 일반 문자열이 아니라 정규식
$1, $2replaceAll 교체문에서 그룹 참조
반복 치환문자열 전체를 계속 훑어서 느릴 수 있음

괄호 제거, 짝 제거, 인접 문자 제거처럼 상태 관리가 필요한 문제는 정규식보다 스택이 낫다.