개발공부/C++

[C++] regex 정규표현식 라이브러리

예슬예 2022. 1. 28. 23:10

https://yeseul-programming.tistory.com/7

 

[프로그래머스/C++]Level 1_숫자 문자열과 영단어

-더보기에 문제 있어요.- 더보기 <문제 설명> 네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자

yeseul-programming.tistory.com

위 문제를 풀다가 regex 정규 표현식 라이브러리에 대해 알게되었고 이를 좀 더 깔끔하게 정리하고 싶어서 쓰는 글..

 

regex에 관련된 함수로는 아래와 같이 있다. ((#include <regex> => 필수!!!!!))

  • std::regex_match : 주어진 문자열이 주어진 규칙에 match 되는지 판별
  • std::regex_search : 주어진 문자열에서 원하는 패턴의 문자열을 검색할 때 
  • std::regex_replace : 주어진 문자열에서 원하는 부분의 문자열을 다른 문자열로 치환할 때

std::regex_match 

예시를 통해 먼저 설명하자면,

int main(void) {
	vector<string> str = { "yeseul-23", "yesol-100" };
	regex re("\\D*-\\d{2}"); 
    
    	cout << boolalpha << regex_match(str[0], re) << endl;
	cout << boolalpha << regex_match(str[1], re) << endl;
    
	return 0;
}
<결과>
true
false

정규 표현식 객체 re에 적당한 규칙을 작성해준다. 그리고 regex_match를 통해 주어진 문자열이 해당 규칙에 해당하는 지 체크해주는 걸 볼 수 있다. 두번째 문장이 false 라는 결과가 나타난 것은 2자리수만 올 수 있는 자리에 100 으로 3자리 숫자가 왔기 때문에 규칙을 만족하지 않는다고 판별한 것이다. 

<<<<<<<<정규 표현식 객체에 넣을 문법과 관련된 키워드들 정리는 더보기>>>>>>>>

더보기

^x // '^'은 문자열의 시작을 표현하며, x문자로 시작됨을 의미

x$ // '$'은 문자열의 종료를 표현하며, x문자로 종료됨을 의미

.x // '.'은 개행문자 \n을 제외한 다른 모든 문자를 의미

x+ // '+'은 1회 이상 반복을 의미, x문자가 1번 이상 반복됨을 의미 ({1,}과 동일)

x* // '*'은 0회 이상 반복을 의미, x문자가 0번 이상 반복됨을 의미 ({0,}과 동일)

x? // '?'은 0 or 1개 문자 매칭 의미, x문자가 존재할 수도 있고 안할수도 있다는 의미 ({0,1}과 동일)

x|y // '|'은 or를 표현, x 또는 y가 나온다는 의미

(x) // '()'은 그룹을 표현, 괄호로 묶인 패턴을 의미 ((abc){3}와 같이 사용해서 abcabcabc를 검출하는데 쓰임)

x{n} // '{}'은 반복을 의미, x가 n번 반복됨을 의미

x{n,} // '{,}'은 반복을 의미, x가 n번 이상 반복됨을 의미

x{n,m} // '{}'은 반복을 의미, x가 n번 이상 m번 이하로 반복됨을 의미

[xy] // '[]'은 x또는 y를 찾는다는 의미, [a-z0-9]이면 알파벳 소문자 또는 숫자를 찾는다는 의미

[^xy] // '[^]'은 not을 의미, x 및 y 를 제외하고 찾는다는 의미

[a-z] // '[-]'은 a ~ z 를 찾는다는 의미

\d // '\d'은 digit으로 숫자를 의미

\D // '\D'은 not digit으로 숫자를 제외하고 나머지 다른 문자를 의미

\s // '\s'은 space로 공백문자를 의미

\S // '\S'은 not space로 공백문자를 제외한 나머지 다른 문자를 의미

\t // '\t'은 tap을 의미

\w // '\w'은 알파벳 대문자,소문자와 숫자를 의미, [A-Za-z0-9]을 의미

\W // '\W'은 not \w, 즉 \w를 제외한 특수문자를 의미

​출처 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=jinhan814&logNo=222090272427

추가로 smatch 형 변수 match와 정규표현식에서 ()를 이용하여 regex_match(str, match, re); 을 쓴다면 ()속 내용을 match에 받아낼 수 있다. 이후 match.str()를 이용하면 해당 문자열을 손쉽게 사용할 수 있다.

 

std::regex_search 

위의 regex_match에서 자세히 설명하여 이건 딱히 설명할 게 없다. 위의 match는 문자열 전체가 완전히 규칙을 만족하는지 보는 거였다면 search는 긴 문자열 중 찾는 문자열 혹은 규칙이 하나라도 존재하면 만족하는 함수이다.

int main(void) {
	string str = "yeseul-23 yesol-100";
	regex re("yes");
	smatch match;
	while (regex_search(str, match, re)) {
		cout << match.str() << endl;
		str = match.suffix();
	}
	return 0;
}

regex_match 코드와 약간 다르지만, 위 str 문장에서 yes 라는 문자열이 포함되어 있는지, 있다면 match되는 해당 ㅜㄴ자열을 받을 수 있도록 한 코드이다. match.suffix()는 match된 문자열 뒤의 문자열을 반환하는 함수이다. 이게 없다면 while문은 계속 같은 str을 검색하게 되고 그렇다면 무한루프를 돌 것....

나는 이를 일정 문자열로 비교했지만 아까 regex_match에서 했듯 정규표현식 문법을 이용하여 검색할 수도 있다.

 

std::regex_replace

이 메소드가 내가 프로그래머스 문제에서 사용했던 것이다. 마치 search와 replace가 합쳐진 형태라고 생각하면 된다.

int main(void) {
	string str = "yeseul-23 yesol-100";
	regex re("\\d{3}");
	str = regex_replace(str, re, "99");
	cout << str << endl;
	return 0;
}

위와 같이 작성하면 3자리 숫자는 모두 99로 변경하게 된다. 위 코드의 결과는

yeseul-23 yesol-99

가 된다. 

그리고 위 코드를 작성하면서 알게된건데, 정규식 문법을 작성할 때 괄호 안에서도 띄어쓰기를 하면 안된다....

regex re("\\d{ 3 }");   --> 이렇게 작성했다가 계속된 오류에 어리둥절 했었다...ㅠㅠ


하여튼 위와 같은 정규식들을 이용하여 좀 더 간편하게 문자열을 matching 하고 search, replace할 수 있었다. 코테에도 문자열 관련된 문제가 많은데 이러한 정규식들을 알고있으면 더 간편하게 풀 수 있는 문제가 많아질 것 같다.

'개발공부 > C++' 카테고리의 다른 글

[C++] BFS(너비 우선 탐색)구현하기  (0) 2022.07.13