일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 스택
- 백트래킹
- BFS
- docker-compose
- ZuulFilter
- 주울
- 서비스 디스커버리
- 스프링 시큐리티
- 유레카
- 달팽이
- 트리
- 다익스트라
- 구간 트리
- Gradle
- spring cloud
- dp
- 플로이드 와샬
- Java
- 비트마스킹
- 완전 탐색
- 이분 탐색
- 구현
- Spring Cloud Config
- Logback
- Zuul
- 게이트웨이
- spring boot
- 이분 매칭
- 도커
- 메모이제이션
- Today
- Total
Hello, Freakin world!
[Java] 정규표현식 핵심만 알고 간단하게 사용하자 본문
자바에서 정규표현식을 사용하기 위해 알아야 하는 클래스는 두 가지입니다.
Pattern 과 Matcher 클래스입니다.
(api 자체에 대한 설명은 넘어가겠습니다. 너무 간단하기 때문입니다!)
일단 예제를 통해 살펴보겠습니다.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexExample {
@Test
public void testRegex() {
String source = "/hello/{id}/{name}"; // 찾을 대상이 포함된 전체 문자열
Pattern pattern = Pattern.compile("\\{[\\w\\d]+\\}"); // 찾고 싶은 문자열 혹은 문자열의 패턴
Matcher matcher = pattern.matcher(source);
while (matcher.find()) {
System.out.println(source.substring(matcher.start(), matcher.end()));
}
}
}
기본적으로 위와 같은 패턴으로 사용됩니다.
찾고 싶은 문자 패턴을 컴파일 -> 패턴을 전체 문자열에 적용 -> Matcher를 이용해 매칭 결과에 접근
여기서 정규표현식이 어렵게 느껴지는 이유는 Pattern.compile('패턴 문자열')에서 '패턴 문자열'을 구성하는 규칙들이
어렵게 느껴지기 때문일겁니다.
저도 이 부분 때문에 책을 사서 보기도 했지만, 수량자, 그룹화, 역참조 등의 용어들로 더 거부감이 느껴지더군요.
그래서 제쳐뒀다가, 최근 필요에 의해 이것저것 테스트해보면서 알아본 결과 생각보다 훨씬 간단한 것들이었습니다.
그럼 핵심 요소 몇 가지를 같이 살펴볼까요?
패턴 문자열을 구성하는 핵심 요소
1. 조건들의 집합 [ ]
간단하게 말하자면 이 대괄호쌍은 조건들의 집합을 나타냅니다.
[\w\s] 처럼 여러 조건들을 나열하거나 제외하는 조건들을 나열해 하나의 문자열과 매치시킬 수 있습니다.
(일부러 \w, \s 들을 처음부터 달달 외우지 마세요! 절대 억지로 외울 필요가 없는 것들입니다. 자연스럽게 외워질때까지 표를 참조하세요.)
2. 역슬래시로 시작되는 메타 문자들 \x
x는 임의의 문자열을 나타내기 위해 사용했습니다. 역슬래시로 시작하는 이 메타문자들은 문자열이나 공백, 경계 등을 매칭합니다. 필요하면 그때그때 표를 보고 참조하며 사용하는 것들 입니다.
3. +, * , { }등 수량 매칭에 사용되는 문자
이 문자들을 이용하면 하나 이상의 문자들을 매칭할 수 있습니다.
위의 1,2는 기본적으로 하나의 문자를 매칭합니다.
X+, [X]+ 과 같은 형태로 사용될 수 있습니다. (X는 임의의 문자, 메타문자를 의미합니다.)
수량 매칭에서도 문자에 따라 디테일이 있습니다. 이것도 외우지마세요!
표를 보고 참조하면서 해도 됩니다.
1,2,3 만 이해해도 예제의 패턴 문자열을 이해할 수 있습니다.
"\\{ [ \\w\\\d ]+ \\}"
\\{ , \\} : { , } 가 수량매칭 메타문자에 포함되기 때문에 이스케이프하기 위해 사용한 것입니다.
[\\w\\d]+ : \w 는 하나의 알파벳 문자, \d는 0~9 숫자를 매칭합니다. 거기에 +가 붙었으므로, 하나 이상의 알파벳 문자 or 숫자들을 매칭합니다.
위의 메타 문자들의 용도만 이해하더라도 대부분의 패턴 매칭은 가능하지만, 어딘가 불편합니다.
아래 print 코드를 살펴보면 굳이 matcher의 start, end 인덱스를 이용해 원본 문자열에서 substring해서 출력하고 있습니다.
만약 위의 패턴 매칭에서 중괄호 안의 문자열만 얻고 싶다면 어떻게 해야할까요?
이럴때 사용할 수 있는게 그룹화입니다.
우선 예제 코드를 먼저 수정해보겠습니다.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexExample {
@Test
public void testRegex() {
String source = "/hello/{id}/{name}";
Pattern pattern = Pattern.compile("\\{([\\w\\d]+)\\}");
Matcher matcher = pattern.matcher(source);
while (matcher.find()) {
// System.out.println(source.substring(matcher.start(), matcher.end()));
System.out.println(matcher.group(1));
}
}
}
보기 쉽게 이스케이프 문자를 제거한 상태에서 패턴 문자열을 살펴봅시다.
{ ( [ \w \d ]+ ) }
괄호로 중괄호 안의 문자열에 매칭하는 부분만 감쌌습니다.
이렇게 괄호로 지정해두면 매칭 됐을 때, 괄호에 해당하는 부분을 참조해 결과에 편하게 접근이 가능합니다.
한 가지 알아둬야 하는 사실은 패턴 문자열에서 그룹에 매겨지는 순서입니다.
위의 예제에서는 1 이라는 인덱스를 이용해 해당 그룹에 접근했습니다.
원리는 간단합니다.
여는 괄호 ( 의 순서로 해당 그룹의 순서가 매겨집니다.
A((B)C) 라는 패턴 문자열이 있다고 합시다.
0번은 무조건 A((B)C) 패턴 문자열 전체를 나타냅니다.
1번은 ((B)C)
2번은 (B) 입니다.
자! 제가 아는 선에서 정규표현식을 최대한 정리해봤습니다.
나머지는 표를 찾아가며 테스트를 몇 번 만들어보세요.
금방 익숙해지실 겁니다!
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java][Reflection] Method 인수의 name 속성 알아내기 (0) | 2020.03.31 |
---|---|
[Java] gradle 프로젝트의 컴파일 옵션 추가하기 (0) | 2020.03.30 |
[Java] ServerSocket(Channel) 동기방식의 accept 동작 방식 (0) | 2020.03.19 |
[Java] CompletableFuture를 이용해 비동기 예외 처리하기 (0) | 2020.03.16 |
[Java] Future 에 대해서 간단하게 정리 (0) | 2020.03.16 |