수업을 진행하면서 c++에서 처음으로 regex를 사용해보았는데 거의 반나절을 삽질한 내용을 포스팅 하려고한다.
진행은 하나 예시를 들어 진행한다.
Example
예시는 다음과 같이 http data가 있다고 할 떄 Host:
이후에 있는 데이터를 뽑아내려고 할 때 로 가정한다.
GET / HTTP/1.1Host: test.gilgil.netConnection: keep-aliveUpgrade-Insecure-Requests:
1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/81.0.4044.138 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,
image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip,
deflateAccept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
데이터를 뽑아낼 떄 정규표현식은 다음과 같이 표현할 수 있다.
"Host: (.*)"
정규표현식 연습은 https://regex101.com/ 와 같은 온라인 사이트를 이용하면 편하다
https://regex101.com/ 사이트를 통해 직접 실험해보면 다음과 같이 Full match는 Host: 가 해당하는 줄이 매칭이 되며, Group1이 우리가 원하는 데이터가 매칭이 되었다는 것을 확인할 수 있다.
그렇다면 직접 코딩을 하여 출력을 해보자
TEST Code #1
#include <iostream>
#include <regex>
using namespace std;
int main() {
string str="GET / HTTP/1.1\n"\
"Host: test.gilgil.net\n"\
"Connection: keep-alive\n"\
"Upgrade-Insecure-Requests: 1\n"\
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36\n"\
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\n"\
"Accept-Encoding: gzip, deflate\n"\
"Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7\n";
regex pattern("Host: (.*)");
smatch tmp;
if(regex_match(str,tmp,pattern)){
cout << "regex_match success : " <<tmp[1].str() << endl;
}
if(regex_search(str,tmp,pattern)){
cout << "regex_search success : " <<tmps[1].str() << endl;
}
return 0;
}
TEST Code #1을 간단하게 설명을 하자면
먼저 str에는 http 데이터를 Text형태로 넣어주었다
regex pattern에는 정규 표현식을 넣어주었으며, 매칭된 후 매칭된 문자열을 저장할 tmp를 선언하였다.
그리고 regex_match와 regex_search 두 함수를 사용하였는데 이는 간단하게 두 함수를 비교를 하기 위하여 사용해주었다.
두 함수 인자에는 검색할 문자열, 매칭된 내용을 저장할 smatch 변수, 정규표현식이 저장된 regex 순으로 넣어준다.
참고로 tmp[0]에는 full match된 문자열이 들어가있으며, tmp[1]에는 첫번쨰 Group이 들어간다 이를 .str()을 사용해주면 string 형태로 반환해준다 .length 등 여러가지가 있으니 알아보면 좋다.
실행 결과는 다음과 같다.
결과를 보면 regex_search함수에서 매칭이 되어서 출력된것을 확인할 수 있다.
여기서 regex_match와 regex_search의 차이를 알 수 있다.
regex_match는 완벽하게 일치하는 매칭일때만 true를 반환하고 search는 부분적이여도 매칭을 해준다.
TEST Code #2
#include <iostream>
#include <regex>
using namespace std;
int main(){
const char packet[] = "\x47\x45\x54\x20\x2f\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a" \
"\x48\x6f\x73\x74\x3a\x20\x74\x65\x73\x74\x2e\x67\x69\x6c\x67\x69" \
"\x6c\x2e\x6e\x65\x74\x0d\x0a\x43\x6f\x6e\x6e\x65\x63\x74\x69\x6f" \
"\x6e\x3a\x20\x6b\x65\x65\x70\x2d\x61\x6c\x69\x76\x65\x0d\x0a\x55" \
"\x70\x67\x72\x61\x64\x65\x2d\x49\x6e\x73\x65\x63\x75\x72\x65\x2d" \
"\x52\x65\x71\x75\x65\x73\x74\x73\x3a\x20\x31\x0d\x0a";
regex pattern1("Host: .*");
regex pattern2("\x48\x6f\x73\x74\x3a\x20(.*)");
cmatch tmp;
string str(packet);
smatch stmp
if(regex_search(packet,tmp,pattern1)){
cout << "pattern1 is success : " <<tmp[1].str() << endl;
}
if(regex_search(str,stmp,pattern2)){
cout << "pattern2 is success : " <<stmp[1].str() << endl;
}
return 0;
}
TEST Code #2는 실제 패킷이 잡혔다는 가정으로 진행을 한다.
먼저 packet 배열에는 실제 http 데이터의 일부분을 넣어주었다.
그리고 pattern을 두가지를 만들었다. 하나는 이전과 같은 패턴이며, 다른 하나는 Host:
를 hex값으로 표현을 한 것이다. 그리고 cmatch와 smacth 두가지를 선언해주었는데, 이는 regex_search에서 문자열을 string으로 넘길건지 char * 형으로 넘길건지 에 따라 cmatch인지 smatch인지 차이가 있다.
실행결과는 다음과 같다.
pattern1이나 pattern2나 char *이나 string 형이나 차이없이 같은 결과가 나온것을 확인할 수 있다.