3 분 소요

  • (C++11~) regex_match()가 추가되어 문자열의 전체가 정규 표현식과 일치하는지 검사할 수 있습니다.
  • (C++11~) regex_search()가 추가되어 문자열의 일부가 정규 표현식과 일치하는지 검사할 수 있습니다.
  • (C++11~) regex_iterator가 추가되었습니다. 문자열 전체에 대해 regex_search() 한 결과의 이터레이터입니다.
  • (C++11~) regex_replace()가 추가되어 문자열에서 정규 표현식과 일치하는 부분을 수정할 수 있습니다.

개요

C++11 부터 STL 에서는 정규 표현식 관련 개체와 유틸리티가 제공되어 패턴이 매칭되는 문자열을 쉽게 검사하고 수정할 수 있습니다.

항목 내용
basic_regex (C++11~) 정규 표현식을 저장합니다.(regex_match() 참고)
* regex : basic_regex<char> 입니다.
* wregex : basic_regex<wchar_t> 입니다.
sub_match (C++11~) (작성중)
match_results (C++11~) 정규 표현식의 매칭 결과를 저장합니다.(regex_search() 참고)
* cmatch : match_result<const char*> 입니다.
* wcmatch : match_result<const wchar_t*> 입니다.
* smatch : match_result<string::const_iterator> 입니다.
* wsmatch : match_result<wstring::const_iterator> 입니다.
regex_match() (C++11~) 문자열의 전체가 정규 표현식과 일치하는지 검사합니다.
regex_search() (C++11~) 문자열의 일부가 정규 표현식과 일치하는지 검사합니다.
regex_replace() (C++11~) 문자열에서 정규 표현식과 일치하는 부분을 수정합니다.
regex_iterator (C++11~) 문자열 전체에 대해 regex_search() 한 결과의 이터레이터입니다.
* cregex_iterator : regex_iterator<const char*> 입니다.
* wcregex_iterator : regex_iterator<const wchar_t*> 입니다.
* sregex_iterator : regex_iterator<string::const_iterator> 입니다.
* wsregex_iterator : regex_iterator<wstring::const_iterator> 입니다.
regex_token_iterator (C++11~) (작성중)
regex_error (C++11~) (작성중)
regex_traits (C++11~) (작성중)
syntax_option_type (C++11~) (작성중)
match_flag_type (C++11~) (작성중)
error_type (C++11~) (작성중)

정규 표현식

정규 표현식은 문자열이 특정한 패턴 규칙과 일치하는지 검사 및 수정하는 형식 언어입니다.

정규 표현식은 다음과 같은 메타 문자를 이용하여 패턴 규칙을 표현합니다.

항목 내용
. \n을 제외한 모든 문자를 나타냅니다.
[] []사이의 문자들과 매칭되는지를 나타냅니다.
[abc]a, b, c중 한개의 문자를 뜻합니다.
- 두문자 사이의 범위를 나타냅니다.
[a-zA-Z]는 알파벳 대소문자중 한개와 매칭되는지를 뜻합니다.
^ 반대를 나타냅니다.
[^0-9]는 숫자가 아닌 문자를 뜻합니다.
\d 숫자를 나타냅니다.
[0-9]와 동일합니다.
\D 숫자가 아닌 것을 나타냅니다.
[^0-9]와 동일합니다.
\s 공백 문자를 나타냅니다.
[ \t\n\r\f\v]와 동일합니다.
\S 공백 문자가 아닌 문자를 나타냅니다.
[^ \t\n\r\f\v]와 동일합니다.
\w 문자와 숫자를 나타냅니다.
[a-zA-Z0-9_]와 동일합니다.
\W 문자와 숫자가 아닌문자를 나타냅니다.
[^a-zA-Z0-9_]와 동일합니다.
* 이전 문자가 0부터 무한대로 반복되는 것을 나타냅니다.
.*은 임의의 숫자나 문자가 무한히 반복되는 것을 뜻합니다.
hel*ohelo, hello, helllo등이 모두 매칭됩니다.
{m} 이전 문자가 m번 반복되는 것을 나타냅니다.
hel{3}ohelllo만 매칭됩니다.
{m,n} 이전 문자가 m ~ n번 반복되는 것을 나타냅니다.
{m,} 이전 문자가 m번 이상 반복되는 것을 나타냅니다.
{,n} 이전 문자가 m번 이하 반복되는 것을 나타냅니다.
{,n} 이전 문자가 m번 이하 반복되는 것을 나타냅니다.
? {0, 1}과 동일합니다.
| 왼쪽과 오른쪽을 논리 OR로 평가합니다.
() 괄호내의 것을 문자 그룹으로 만듭니다.
(left|right)leftright 문자열중 하나만 일치하면 매칭됩니다.
또한 괄호내의 것을 캡쳐합니다.

regex_match()

문자열의 전체가 정규 표현식과 일치하는지 검사합니다.

다음 코드는 ab[,:].*과 일치하는 문자열을 검사하는 예입니다. ab,ab:로 시작하는 모든 문자열을 검색합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
std::vector<std::string> v{"abcd", "ab,cd", "ab:cd", "ab cd"}; 
std::vector<std::string> result;

// ab 다음에 `,` 또는 `:` 가 있는 문자열 검색하되, 모든 문자(.)가 0부터 무한대로 반복(*)됨.
std::regex regex{"ab[,:].*"}; 

for(auto str : v) {
    if (std::regex_match(str, regex)) {
        result.push_back(str);
    }    
}

EXPECT_TRUE(result.size() == 2 && result[0] == "ab,cd" && result[1] == "ab:cd");

regex_search()

문자열의 일부가 정규 표현식과 일치하는지 검사합니다.

다음 코드는 전화번호가 있는 부분을 검사하는 예입니다.

smatchmatch_result<string::const_iterator> 로서 매칭 결과를 저장합니다. str()을 이용하여 매칭된 문자열을 구할 수 있으며, suffix()를 이용하여 매칭된 다음 위치부터 다시 검사합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::string str{
    R"(Tango's phone number is 010-1234-5678. 
His home phone number is 02-123-4567.)"
}; 
std::vector<std::string> result;

// 010- 또는 02-로 시작하고, 숫자가 3~4개 반복, -, 숫자가 4개 반복
std::regex regex{R"((010|02)-[0-9]{3,4}-[0-9]{4})"}; // 특수 기호가 있으므로, Raw String 리터럴로 표기하는게 좋습니다.
std::smatch matchResult;

while(std::regex_search(str, matchResult, regex)) {
    result.push_back(matchResult.str()); 

    str = matchResult.suffix(); // matchResult 다음 위치의 문자열입니다. str에 대입하여 다음번 매칭을 찾습니다.
}

EXPECT_TRUE(result.size() == 2 && result[0] == "010-1234-5678" && result[1] == "02-123-4567");

regex_iterator

문자열 전체에 대해 regex_search() 한 결과의 이터레이터입니다. 상기 예제에서는 while()suffix() 를 사용했지만, 이터레이터를 이용하여 다음과 같이 간소화 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::string str{
    R"(Tango's phone number is 010-1234-5678. 
His home phone number is 02-123-4567.)"
}; 
std::vector<std::string> result;

std::regex regex{R"((010|02)-[0-9]{3,4}-[0-9]{4})"};

// 문자열 전체의 regex_search() 결과를 이터레이터로 리턴합니다. 
auto itr{std::sregex_iterator(str.begin(), str.end(), regex)};
auto endItr{std::sregex_iterator()};

for (; itr != endItr; ++itr) {
    result.push_back(itr->str());
}

EXPECT_TRUE(result.size() == 2 && result[0] == "010-1234-5678" && result[1] == "02-123-4567");

regex_replace()

문자열에서 정규 표현식과 일치하는 부분을 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
std::string str{
    R"(Tango's phone number is 010-1234-5678. 
His home phone number is 02-123-4567.)"
}; 

std::regex regex{R"((010|02)-[0-9]{3,4}-[0-9]{4})"};

// 매칭된 결과를 수정합니다.
std::string result{std::regex_replace(str, regex, "xxx-xxxx-xxxx")};

EXPECT_TRUE(result == R"(Tango's phone number is xxx-xxxx-xxxx. 
His home phone number is xxx-xxxx-xxxx.)");

정규 표현식의 캡쳐를 이용하면, 매칭된 부분의 값을 이용하여 바꿀 수 있습니다.

다음 예제에서는 괄호를 이용하여 ([0-9]{4}_[0-9]{2}_[0-9]{2})을 캡쳐하고, 매칭된 문자열을 바꿀때 $1을 이용하여 캡쳐된 값으로 바꿉니다.

1
2
3
4
5
6
7
8
9
std::string str{R"(file_2020_01_01.txt, file_2020_01_02.txt)"}; 

// ([0-9]{4}_[0-9]{2}_[0-9]{2})을 캡쳐합니다.
std::regex regex{R"(file_([0-9]{4}_[0-9]{2}_[0-9]{2})[.]txt)"};

// 매칭된 결과에서 캡쳐된 내용인 $1을 출력합니다.
std::string result{std::regex_replace(str, regex, "$1_file.txt")};

EXPECT_TRUE(result == R"(2020_01_01_file.txt, 2020_01_02_file.txt)");   

태그:

카테고리:

업데이트:

댓글남기기