[c++] 정규 표현식 regex
include <regex>
정규 표현식 기반, 문자열에 대한 탐색/교체
정규 표현식 기호 종류
. | 임의의 한 문자를 나타낸다. 예를 들면, a.c → "abc" | "a2c" | "a&c" 등. |
* | 앞의 요소가 '0'번 이상 반복됨을 나타낸다. 예를 들면, a* → "" | "a" | "aa" 등. |
+ | 앞의 요소가 '1'번 이상 반복됨을 나타낸다. 예를 들면, a* → "a" | "aa" 등. ( "" 은 x) |
? | 앞의 요소가 0번 또는 1번 나타난다. 예를 들면, a? → "" | "a" |
\\d | 숫자를 나타낸다. 0 ~ 9 까지 숫자 문자. |
\\w | 글자를 나타낸다. 알파벳, 숫자, 밑줄(_) |
\\b | 단어 경계를 나타낸다. \\b ~~~ \\b (단어의 시작과 끝을 구분하는 용도) |
[xxx..] | 대괄호 안에 있는 문자와 일치하는 글자를 나타낸다. 예를 들면, [abc] → "a" | "b" | "c". |
[^xxx..] | 대괄호 안에 있는 문자와 일치하지 않는 글자를 나타낸다. 예를 들면, [^abc] → "a" | "b" | "c" 를 제외한 모든 글자 |
^x | "x" 로 시작하는 문자열 또는 줄을 나타낸다. 예를 들면, ^a → 'a' 로 시작하는 문자열. |
$x | "x" 로 끝나는 문자열 또는 줄을 나타낸다. 예를 들면, ^a → 'a' 로 끝나는 문자열. |
{m, n} | 앞의 요소가 m번 이상 n번 이하로 포함된다는 것을 나타낸다. ex) a{1, 3} → a가 1번이상, 3번 이하 포함된 문자열 |
{min} | 앞의 요소가 min번 이상 포함된다는 것을 나타낸다. ex) a{1} → a가 1번이상 포함된 문자열 |
() | 그룹핑 : 말 그대로 조건에 그룹을 표현하는 것. ex) ( //d+001* )+ 캡쳐 그룹 : 괄호 안의 조건 해당하는 글자를 골라내 따로 저장하는 용도 (regex_match 에서 씀) |
| | or 연산 |
\ | 이스케이프 문자. ex) \. 은 '.' 이 임의의 한 문자를 나타내기 때문에 말그대로 마침표(.) 글자를 표현하기 위함 \\, \a, \b, \n, \f, \r, \t, \v. 백슬래시, 경고, 백스페이스, 줄 바꿈 , 양식 피드, 캐리지 리턴, 가로 탭, 세로 탭. |
[ x - y ] | ex) [a-c] → a, b, c 중 매칭되는 것 하나 |
[예제]
"(100+1+ | 01)+" 라는 표현식 이 있다고 했을 때,
- 100+ : 10 뒤에 0이 1개 이상 나오는 문자열
- 1+ : 1이 1개 이상 나오는 문자열
- 01 : "01" 문자열
- | : 100+1+ 패턴이나 01 패턴 중 하나
- () : 위 패턴이 하나 이상 반복되는 문자열
<3자리 국가코드, 4자리 중간번호, 4자리 마지막 번호> 로 표현 되는 핸트폰 번호 정규 표현식
"\\b010-\\d{4}-\\d{4}\\b"
- \\b ~ \\b : 단어의 경계
- 010- : "010-" 으로 시작되는 문자열
- - : "-" 글자
- \\d{4} : 4글자 숫자 인 문자열
"01[0-6]{1}-\\d{3,4}-\\d{4}"
- 01 : "01" 로 시작되는 문자열
- [0-6]{1} : 0~6 까지의 숫자 문자 1개. ( {1} 생략 가능)
- \\d{3,4} : 3글자 혹은 4글자의 숫자 문자열
Regular expressions library (since C++11) - cppreference.com
Regular expressions library (since C++11) - cppreference.com
Regular expressions library The regular expressions library provides a class that represents regular expressions, which are a kind of mini-language used to perform pattern matching within strings. Almost all operations with regexes can be characterized by
en.cppreference.com
미리보기
std::regex pattern("Get|GetValue"); std::cmatch m; std::regex_search ("GetValue", m, re); // returns true, and m[0] contains "Get" std::regex_match ("GetValue", m, re); // returns true, and m[0] contains "GetValue" std::regex_search ("GetValues", m, re); // returns true, and m[0] contains "Get" std::regex_match ("GetValues", m, re); // returns false |
regex
정규 표현식 객체
가장 먼저 정규 표현식 객체를 정의해야 한다.
std::regex pattern("db-\\d*-log\\.txt"); |
정규 표현식 문법에는 여러 종류가 있다.
- ECMAScript: JavaScript 및 .NET 언어에서 사용하는 문법과 가장 가깝습니다. (기본값)
- basic: POSIX basic 정규식 또는 BRE입니다.
- extended: POSIX extended 정규식 또는 ERE입니다.
- awk: 이 extended경우 인쇄되지 않는 문자에 대한 이스케이프가 더 많이 있습니다.
- grep: 이 basic경우 줄 바꿈(\n) 문자가 교대로 구분됩니다.
- egrep: 이 extended경우 줄 바꿈 문자가 교대로 구분할 수도 있습니다.
그리고 여러 플래그를 적용할 수도 있다.
- icase: 일치 시 대/소문자를 무시합니다.
- nosubs: 표시된 일치 항목(즉, 괄호 안의 식)을 무시합니다. 대체 항목이 저장되지 않습니다.
- optimize: 정규 표현식 객체를 생성하는데에는 시간이 좀 더 걸리지만 정규 표현식 객체를 사용하는 작업은 좀 더 빠르게 수행
- collate: 로캘 구분 데이터 정렬 시퀀스(예: 양식 [a-z]범위)를 사용합니다.
- (0개 이상의 플래그를 문법과 결합하여 정규식 엔진 동작을 지정할 수 있다)
std::regex pattern("db-\\d*-log\\.txt", std::regex::grep | std::regex::icase); |
regex_match
문자열 매칭하기.
해당 문자열이 정규 표현식과 일치하는지 확인하는 함수. (bool 반환)
<"db-(숫자)-log.txt" 파일 이름 형식과 맞는지 확인하는 예제>
#include <iostream>
#include <regex>
#include <vector>
using namespace std;
int main()
{
// 확인할 파일 이름들.
vector<string> file_names = {"db-123-log.txt", "db-124-log.txt",
"not-db-log.txt", "db-12-log.txt",
"db-12-log.jpg"};
regex pattern("db-\\d*-log\\.txt");
for (const auto &file_name : file_names)
{
// std::boolalpha 는 bool 을 0 과 1 대신에 false, true 로 표현하게 해줍니다.
cout << file_name << ": " << std::boolalpha << regex_match(file_name, re) << endl;
}
}
매칭되는 문자열 중, 부분 뽑아내기
정규 표현식과 일치하는 문자열 중에 일부분 추출하여 저장하는 방법
- () 캡처 그룹을 사용하여 정규 표현식 중 원하는 부위에 감싼다.
- smatch 타입 변수에 저장한다.
< 핸드폰 번호 중, 중간/마지막 번호 뽑아내는 예제>
vector<string> phone_numbers = { "010-1234-5678", "000-123-4567",
"011-1234-5567", "010-12345-6789",
"123-4567-8901", "010-1234-567" };
regex pattern("01[0-6]{1}-(\\d{3,4})-(\\d{4})");
smatch match; // 매칭된 결과를 string 으로 보관
for (const auto& number : phone_numbers) {
if (regex_match(number, match, re)) {
for (size_t i = 0; i < match.size(); i++) {
cout << "Match : " << match[i].str() << endl;
}
cout << "-----------------------\n";
}
}
// 그냥 match.str() 을 한다면 가장 처음 수집된 문자열이 반환된다.
regex_search
문자열 검색하기.
해당 문자열중에 정규 표현식과 일치하는 "일부" 문자열이 있는지 확인하는 함수. (bool 반환)
<문자열에서 숫자가 있는지 확인 및 뽑아내는 예제>
#include <iostream>
#include <string>
#include <regex>
std::string extractNumbers(const std::string& input) {
std::regex pattern("\\d+"); // Regular expression to match one or more digits
std::smatch match;
std::string result;
// Search the input string for numbers
if (std::regex_search(input, match, re)) {
result = match.str(); // Extract the first matched number
}
return result;
}
int main() {
std::string input = "The price is 42 dollars";
std::string numbers = extractNumbers(input);
if (!numbers.empty()) {
std::cout << "Found number: " << numbers << std::endl;
} else {
std::cout << "No numbers found." << std::endl;
}
return 0;
}
문자열 반복 검색하기.
regex_search() 는 반복 호출 시, 그냥 기존 문자열 기준으로 검색된 같은 패턴을 반복해서 반환한다.
검색된 패턴 이후 부터 다시 검색하는 방법은 match.suffix() 를 호출하여 반환된 문자열 기준으로 다시 검색하는 것이다.
- match.suffix() 은 기존 문자열에서 검색된 패턴 바로 뒤 부터 끝까지 해당하는 ssub_match 객체를 리턴한다.
- ssub_match 객체는 string 으로 캐스팅 변환하는 연산자가 들어있다.
<문자열에 존재하는 모든 숫자를 찾아내어 뽑아내는 예제>
std::vector<string> extractNumbers(const std::string& input) {
std::regex pattern("\\d+"); // Regular expression to match one or more digits
std::smatch match;
std::vector<string> result;
string check = input;
// Search the input string for numbers
while (std::regex_search(check, match, re)) {
result.push_back(match.str());
check = match.suffix();
}
return result;
}
int main() {
std::string input = "The price is 42 or 75 dollars";
std::vector<string> numbers = extractNumbers(input);
if (!numbers.empty()) {
for(string str : numbers)
std::cout << "Found number: " << str << std::endl;
}
else {
std::cout << "No numbers found." << std::endl;
}
return 0;
}
regex_iterator.
iterator 를 이용하면 좀 더 편리한 반복 검색을 수행할 수 있다.
- sregex_iterator 단독 선언은 반복자의 종단(end) 를 의미한다.
std::vector<string> extractSecondNumber(const std::string& input) {
std::regex pattern("\\d+"); // Regular expression to match one or more digits
std::sregex_iterator currentMatch(input.begin(), input.end(), re);
std::sregex_iterator lastMatch;
std::vector<std::string> matches;
while (currentMatch != lastMatch) {
matches.push_back(currentMatch->str());
++currentMatch;
}
return matches; // Return the second matched number
}
int main() {
std::string input = "There are 42 apples and 23 oranges";
std::vector<string> Numbers = extractSecondNumber(input);
if (!Numbers.empty()) {
for(string str : Numbers)
std::cout << "Found number: " << str << std::endl;
}
else {
std::cout << "numbers not founded." << std::endl;
}
return 0;
}