C++11부터 표준 라이브러리에 정규 표현식(regex)이 추가된 문자열을 보다 강력하고 유연하게 처리할 수 있는 방법에 대해 알아보려고 한다.
해당 라이브러리를 사용하면 특정 패턴을 쉽게 검색, 일치 검사, 치환, 분할할 수 있다.
정규 표현식 (Regular Expression)
문자열에서 특정한 패턴을 찾거나 조작하기 위한 도구.
다양한 프로그래밍 언어에서 지원되며, 일정한 규칙을 가진 문자열을 검색, 검증, 변환하는 데 사용된다.
#include <regex>
문법
| 표현 | 설명 | 패턴 | 예시 |
|---|
| . | 임의의 한 문자 | a.c | abc, a#c, a0c |
| * | 앞의 요소가 0번 이상 반복 | a* | , a, aa |
| + | 앞의 요소가 1번 이상 반복 | a+ | a, aa, aaa |
| ? | 앞의 요소가 0번 또는 1번 | a? | , a |
| \d | 숫자를 나타냄 | | 0 ~ 9 까지의 수 |
| \w | 문자를 나타냄 | | 알파벳, 숫자, 밑줄(_) |
| \s | 공백 문자를 나타냄 | | 스페이스, Tab(\t), 개행 문자(\n), 캐리지 리턴(\r) |
| \b | 단어 경계를 나타냄 | | 단어의 시작과 끝을 나타냄 |
| [...] | 대괄호 안의 어떤 문자와도 일치 | [a,b,c] | a, b, c |
| [^...] | 대괄호 안의 어떤 문자와도 일치하지 않음 | [^a,b,c] | a, b, c 를 제외한 문자와 모두 일치 |
| ^ | 문자열 또는 줄의 시작 | ^a | a 로 시작하는 문자열과 일치 |
| $ | 문자열 또는 줄의 끝 | $a | a 로 끝나는 문자열과 일치 |
예시 - 이메일 주소 검증
이메일 계정 부분 @ 도메인 . 최상위 도메인
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
- ^ : 문자열 시작
- [a-zA-Z0-9._%+-]+ : 이메일 계정 부분 (알파벳, 숫자, . , _, %, +, - 포함 가능)
- @ : @ 기호
- [a-zA-Z0-9.-]+ : 도메인 이름 (. 또는 - 포함 가능)
- \. : 도메인과 최상위 도메인(TLD) 사이의 점(.)
- [a-zA-Z]{2,} : 최상위 도메인 (예: com, net, org 등 최소 2글자 이상)
- $ : 문자열의 끝
예시 - 전화번호 검증
^01[016789]-\d{3,4}-\d{4}$
- ^ : 문자열의 시작
- 01[016789] : 01 다음에 0, 1, 6, 7, 8, 9 중 하나 (예: 010, 011, 016 등)
- - : 중간 - 기호
- \d{3,4} : 3~4자리 숫자 (예: 123 또는 1234)
- - : 중간 - 기호
- \d{4} : 4자리 숫자 (예: 5678)
- $ : 문자열의 끝
regex 클래스
| 클래스명 | 설명 |
|---|
| regex | 정규표현식을 저장하는 클래스 |
| smatch | 문자열 검색 결과를 저장하는 클래스 (string 대상) |
| cmatch | 문자열 검색 결과를 저장하는 클래스 (C 스타일 문자열 char* 대상) |
| regex_iterator | 문자열에서 모든 정규표현식 매칭을 반복적으로 찾는 반복자 |
| regex_token_iterator | 정규표현식을 기준으로 문자열을 토큰화하는 반복자 |
| regex_error | 정규표현식에서 예외가 발생할 경우 던지는 예외 클래스 |
주요 regex 메서드
regex_match
문자열 전체가 정규식과 일치하는지 확인하는 메서드
bool regex_match(string& str, regex& re);
bool regex_match(string& str, smatch& match, regex& re);
| 파라미터 | 타입 |
|---|
| str | 검사할 문자열 |
| re | 정규표현식 객체 (regex) |
| match | 매칭된 결과를 저장할 객체 (smatch) |
| 반환값 | 조건 |
|---|
| true | 전체 문자열이 정규식과 완전히 일치 |
| false | 일치하지 않음 |
예시
string str = "12345";
regex pattern(R"(\d{5})"); // 5자리 숫자
if (regex_match(str, pattern))
cout << "일치" << '\n';
else
cout << "불일치" << '\n';
regex_search
문자열에서 정규식과 일치하는 부분이 있는지 검색하는 메서드
bool regex_search(string& str, regex& re);
bool regex_search(string& str, smatch& match, regex& re);
| 파라미터 | 타입 |
|---|
| str | 검사할 문자열 |
| re | 정규표현식 객체 (regex) |
| match | 매칭된 부분 문자열을 저장할 객체 (smatch) |
| 반환값 | 조건 |
|---|
| true | 문자열 내부에서 일부라도 일치하는 부분이 있음 |
| false | 일치하는 부분이 없음 |
예시
string text = "전화번호는 010-1234-5678 입니다.";
regex phone_regex(R"(\d{3}-\d{4}-\d{4})");
smatch match;
if (regex_search(text, match, phone_regex))
cout << "전화번호 : " << match.str() << '\n'; // 출력 결과 : 010-1234-5678
regex_replace
정규식과 일치하는 부분을 특정 문자열로 대체하는 메서드
string regex_replace(string& str, regex& re, string& replacement);
| 파라미터 | 타입 |
|---|
| str | 원본 문자열 |
| re | 정규표현식 객체 (regex) |
| replacement | 대체할 문자열 |
예시
string text = "내 이메일은 example@email.com 입니다.";
regex email_regex(R"([\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,})");
string result = regex_replace(text, email_regex, "[이메일 숨김]");
cout << result << '\n'; // 출력 결과 : 내 이메일은 [이메일 숨김] 입니다.
마무리
문자열을 강력하고 유연하게 처리할 수 있는 regex STL 에 대해 알아보았다.
BOJ 1013 : Contract 문제를 풀다가 처음 알게된 STL 이지만,
도움이 될 것 같아 정리해보았다.