목차
Regex(정규표현식, Regular Expression)란?
Regex는 문자열에서 특정 패턴을 검색, 일치, 변환, 분리하기 위한 표현식으로 문자열을 효율적으로 처리할 수 있도록 설계된 규칙 기반의 언어이며 주로 아래 5개의 목적을 위해 사용된다.
- 검색(Search): 특정 패턴이 문자열 내에 존재하는지 확인.
- 일치(Match): 문자열이 특정 패턴과 완전히 일치하는지 확인.
- 추출(Extract): 문자열에서 특정 부분을 추출.
- 분리(Split): 특정 패턴을 기준으로 문자열을 분리.
- 변환(Replace): 특정 패턴을 찾아 다른 값으로 대체
Regex의 기본 구성 요소
Regex는 문자와 메타문자로 구성된다.
1. 문자 (Literal Characters)
- 특정 문자나 문자열 자체를 찾는다.
- 예: "abc"는 문자열에 "abc"가 있는지 찾는다.
2. 메타문자 (Metacharacters)
메타문자는 특별한 의미를 가지는 문자들이다.
. | 임의의 한 문자 (줄바꿈 제외) | "a.c"는 "abc", "adc" |
^ | 문자열의 시작 | "^abc"는 "abc"로 시작 |
$ | 문자열의 끝 | "xyz$"는 "xyz"로 끝남 |
* | 0회 이상 반복 | "a*"는 "a", "aa" |
+ | 1회 이상 반복 | "a+"는 "a", "aa" |
? | 0회 또는 1회 | "a?"는 "a" 또는 없음 |
{n} | 정확히 n번 반복 | "a{3}"는 "aaa" |
{n,} | 최소 n번 반복 | "a{2,}"는 "aa", "aaa" |
{n,m} | 최소 n번, 최대 m번 반복 | "a{2,4}"는 "aa", "aaa", "aaaa" |
[] | 문자 클래스. 괄호 안의 문자 중 하나와 일치 | "[abc]"는 "a", "b", "c" |
[^] | 부정 문자 클래스. 괄호 안의 문자가 아닌 문자와 일치 | "[^abc]"는 "d", "e" |
` | ` | OR 연산자 |
() | 그룹화 (캡처 그룹) | "(abc)"는 그룹으로 캡처 |
\ | 이스케이프 문자. 메타문자를 일반 문자로 취급 | "\."는 "." 찾기 |
Regex의 특수 시퀀스
1. 문자 클래스 (Character Classes)
- 특정 문자 유형을 지정한다.
표현식의미예시
\d | 숫자 ([0-9]) | "123" |
\D | 숫자가 아님 ([^0-9]) | "abc" |
\w | 단어 문자 ([a-zA-Z0-9_]) | "word1" |
\W | 단어 문자가 아님 | "!@#" |
\s | 공백 문자 | " " |
\S | 공백 문자가 아님 | "abc" |
2. 앵커 (Anchors)
- 특정 위치를 기준으로 패턴을 일치시킨다.
^ | 문자열의 시작 | ^Hello는 "Hello World"에서 "Hello" 찾음 |
$ | 문자열의 끝 | World$는 "Hello World"에서 "World" 찾음 |
Pattern 클래스
- 정규표현식 패턴을 정의하고 이를 컴파일하는 역할을 한다.
- 정적 메서드로 정규표현식을 컴파일하고 Matcher 객체를 생성하는 데 사용된다.
- Pattern 객체는 한 번 컴파일되면 재사용이 가능하므로, 여러 번 매칭해야 할 경우 성능이 좋다.
compile(String regex)
- 정규표현식을 컴파일하여 Pattern 객체를 반환한다.
- 정규식의 문법 오류가 있을 경우 PatternSyntaxException이 발생한다.
Pattern pattern = Pattern.compile("\\d+"); // 숫자 하나 이상
matcher(CharSequence input)
- 입력 문자열에 대해 매칭을 수행할 Matcher 객체를 생성한다.
Matcher matcher = pattern.matcher("123abc");
split(CharSequence input)
- 정규표현식을 기준으로 문자열을 분리한다.
String[] result = pattern.split("apple,banana,orange");
pattern()
- Pattern 객체에 저장된 정규표현식을 반환한다.
Matcher 클래스
- 입력 문자열과 정규표현식을 매칭하는 데 사용된다.
- 매칭된 패턴의 위치, 결과, 그룹을 확인할 수 있다.
find()
- 입력 문자열에서 정규식과 일치하는 다음 부분을 찾는다.
- 반환값: boolean (일치 여부)
while (matcher.find()) {
System.out.println(matcher.group());
}
matches()
- 입력 문자열 전체가 정규식과 일치하는지 확인한다.
- 반환값: boolean
boolean isMatch = matcher.matches();
group()
- 매칭된 문자열을 반환합니다.
- 그룹화된 부분이 있으면 특정 그룹을 반환할 수도 있다.
System.out.println(matcher.group(1)); // 첫 번째 그룹 반환
start()와 end()
- 매칭된 부분의 시작 인덱스와 끝 인덱스를 반환한다.
System.out.println("Start: " + matcher.start() + ", End: " + matcher.end());
replaceAll(String replacement)
- 정규식에 매칭되는 부분을 지정된 문자열로 치환한다.
String result = matcher.replaceAll("replaced");
효율적인 Pattern 객체 사용으로 메모리 낭비 줄이기
1주차 문자열계산기 미션의 나의 코드 중 최적화 할수 있는 부분에 대해 피드백을 받았다.
Pattern pattern = Pattern.compile("//(.)\\\\n.*");
Matcher matcher = pattern.matcher(input);
나의 코드에는 위와같이 여러 메서드에서 매번 새로운 Pattern 객체를 생성하고 있어, 불필요한 객체를 무분별하게 생성하며 메모리 낭비가 일어나 성능 저하가 발생하고 있다.
🔨 개선
// 정규표현식 패턴을 상수로 정의
private static final Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile("//(.)\\\\n.*");
private static final Pattern NUMBERS_AFTER_DELIMITER_PATTERN = Pattern.compile("//.\\\\n(.*)");
private static final Pattern DEFAULT_PATTERN = Pattern.compile("^[0-9,:]*$");
public String getCustomDelimiter(String input) {
Matcher matcher = CUSTOM_DELIMITER_PATTERN.matcher(input);
if (matcher.find()) {
String delimiter = matcher.group(1);
if (delimiter.matches("[0-9]")) {
throw new IllegalArgumentException("숫자는 구분자로 사용할 수 없습니다.");
}
return delimiter;
}
throw new IllegalArgumentException("올바른 커스텀 구분자가 없습니다.");
}
public String getNumbersAfterDelimiter(String input) {
Matcher matcher = NUMBERS_AFTER_DELIMITER_PATTERN.matcher(input);
if (matcher.find()) {
return matcher.group(1);
}
return "";
}
public boolean isCustomDelimiterPattern(String input) {
return CUSTOM_DELIMITER_PATTERN.matcher(input).matches();
}
public boolean isValidDefaultPattern(String input) {
return DEFAULT_PATTERN.matcher(input).matches();
}
위와같이 Pattern 객체를 재사용하여 자주 사용되는 정규표현식 패턴을 priavte static final로 선언하여 클래스 상수로 정의하며 불변성을 보장 받으며 매 메서드 호출마다 새로운 Pattern 개체를 생성하지 않아도 되어 메모리 효율성과 성능 향상을 이룰수 있다.
'외부활동 > 우아한테크코스 [프리코스]' 카테고리의 다른 글
상수관리에 Enum은 필수적인가 ? (0) | 2024.11.01 |
---|---|
[우아한테크코스 7기] 프리코스 2주차 회고 (0) | 2024.10.29 |
우아한테크코스 NsTest,Assertions 톺아보기 (0) | 2024.10.27 |
MVC 패턴 톺아보기 (0) | 2024.10.23 |
[우아한테크코스 7기] 프리코스 1주차 회고 (0) | 2024.10.23 |