본문 바로가기
Regex

regex 메타 문자 사용

by 콩순이냉장고 2021. 9. 4.

메타 문자는 정규 표현식 안에서 특별한 의미가 있습니다. 마침표(.)는 메타문자든 문자하나와 일치하며

여는 대괄호([)도 집합의 시작을 나타내며 메타문자입니다.

그러나. 아래와 같이 대괄호를 찾으려는 정규표현식을 찾을때 어떻게 해야할까?

 

 

예문

var myArray = new Array();

...

if(myArray[0]==0)

...

}

 

정규 표현식

myArray[0]

 

결과

var myArray = new Array();

...

if(myArray[0]==0)

...

}

 

즉 어떤것도 일치하지 않는다

여기서 정규표현식 myArray[0]을 잘살펴보자 대괄호는 집합을 의미하며 0은 0과 일치하는 문자를 찾으라는 뜻이다

즉 myArray0 과 일치할수밖에 없다.

그럼 대괄호를 찾으려면 어떻게 해야할까? 여는대괄호([)와 닫는대괄호(])를 이스케이프 해야한다

아래와 같이

 

정규표현식 

myArray\[0\]

 

결과

var myArray = new Array();

...

if(myArray[0]==0)

...

}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
void input();
string words;
int main() {
    input();
    cout << words << endl;
    cout << "---------------------------------" << endl;
    regex re(R"(myArray\[0\])");
    smatch match;
    while (regex_search(words, match, re)) {
        cout << match[0<< endl;
        words = match.suffix();
    }
}
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
void input();
string words;
int main() {
    input();
    cout << words << endl;
    cout << "---------------------------------" << endl;
    regex re("myArray\\[0\\]");
    smatch match;
    while (regex_search(words, match, re)) {
        cout << match[0<< endl;
        words = match.suffix();
    }
}
cs

 

이번코드는 regex_search를 이용하여 찾는것을 보여줬따 sregex_iterator와 regex_search 둘다 반복해서 사용해서 익히길바랍니다.

 

위 2가지 코드의 차이점이 보이시나요?

하나는 regex re(R"(myArray\[0\])");와 

다른 하나는 regex re("myArray\\[0\\]"); 이거다

첫번째 코드는 리터럴 상수를 사용했고

2번째 코드는 일반 문자열코드를 사용했다 차이점은 리터럴상수는 그대로 문자를 집어넣어 정규표현식을 escape했던것이고

2번째 코드는  c++내에 \를 표현하기위해 \\를 사용하여 \를 escape한다음 \를 표현하여 정규표현식에서 대괄호를 이스케이프한것이다 두가지 차이점을 잘 확인하시길 바랍니다.

 

 

만약 배열요소를 0부터 9까지 일치시키고 싶다면

정규표현식을 myArray\[[0-9]\] 로 작성할수 있습니다.

 

 

역슬래시(\) 물론 내가 글을 쓰고있는컴퓨터는 윈도우라 \는 원단위로 보이지만 역슬래시라고 생각하자역슬래시(\)는 메타문자들을 이스케이프 하는 데 사용합니다. 이말은 역슬래시(\)도 다른 메타 문자들을 이스케이프 하는데 사용합니다.

 

예문

\home\ben\sales\

 

정규표현식

\\

 

결과

\home\ben\sales\

 

여러가지 메타 문자

 

이전 글에서 배웠뜻이 [0-9]는 [0123456789]을 줄인표현이고 어떤 숫자와도 일치합니다.

숫자를 제외한 문자를 찾으려면[^0-9]처럼 제외하는 메타문자를 사용합니다.

그러나 더간단하게 표현하는 클래스가 있습니다.

 

메타 ㅁ누자 설명
\d 숫자 하나[0-9]와 같다
\D 숫자를 제외한 문자 하나[^0-9]와 같다

 

이전에 똑같은 예문을 가져오겠습니다.

 

예문

var myArray = new Array();

...

if(myArray[0]==0)

...

}

 

정규표현식 

myArray\[\d\]

 

결과

var myArray = new Array();

...

if(myArray[0]==0)

...

}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
void input();
string words;
int main() {
    input();
    cout << words << endl;
    cout << "---------------------------------" << endl;
    regex re(R"(myArray\[\d\])");
    smatch match;
    while (regex_search(words, match, re)) {
        cout << match[0<< endl;
        words = match.suffix();
    }
}
cs

 

 

 

이런식으로 메타문자를 사용할수 있다 

다른 메타문자들을 모겠따

 

영숫자 문자와 영숫자가 아닌 문자 찾기

 

메타 문자 설명
\w 대소문자와 밑줄을 포함 모든 영숫자[a-zA-Z0-9_]와 같다
\W 영숫자나 밑줄이 아닌 모든 문자[^a-zA-Z0-9_]와 같다

 

예문

11213

A1C2E3

48075

48237

M1B4F2

90046

H1H2H2

 

정규표현식

\w\d\w\d\w\d

 

결과

11213

A1C2E3

48075

48237

M1B4F2

90046

H1H2H2

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
void input();
string words;
int main() {
    input();
    cout << words << endl;
    cout << "---------------------------------" << endl;
    regex re(R"(\w\d\w\d\w\d)");
    smatch match;
    while (regex_search(words, match, re)) {
        cout << match[0<< endl;
        words = match.suffix();
    }
}
cs

 

 

공백문자와 공백이 아닌 문자 찾기

 

메타 문자 설명
[\b] 역스페이스
\f 페이지 넘김(form feed)
\n 줄바꿈
\r 캐리지 리턴
\t
\v 수직 탭

 

이번 예문에는 콤바로 구분된 (일반적으로 CSV라고 부른다) 레코드가 담겨 있다. 여러분은 데이터에 있는 빈 줄을 모두 제거 한 다음, 이 레코드를 처리해야합니다.

 

예문

"101","Ben","Forta"

"102","Jim","James"    

                             

"103","Roberta","Fobertson"

"104","Bob","Bobson"

 

정규표현식

\r\n\r\n

 

결과

"101","Ben","Forta"

"102","Jim","James"    

                             

"103","Roberta","Fobertson"

"104","Bob","Bobson"

 

\r\n은 줄바꿈과 캐리지 리턴의 조합과 일치합니다. 윈도우에서는 이조합은 줄의 끝을 나타내는데 사용합니다. 따라서 \r\n\r\n을 검색하면 줄 끝이 연속해서 두 번 나오는 부분과 일치하는데 이때 줄의 끝이 두 번 나온다는 것은 바로 두 레코드 사이에 빈 줄이 있음을 의미합니다.

 

 

메타 문자 설명
\s 모든 공백 문자 [\f\n\r\t\v]와 같다
\S 공백 문자가 아닌 모든 문자 [^\f\n\r\t\v]와 같다

그러나 \s나 \S에 역스페이스 메타 문자인 [\b]는 포함되지 않습니다.

 

 

포직스 문자 클래스

분류 내용
[:alnum:] 모든 영숫자[a-zA-Z0-9]와 같다
[:alpha:] 모든 영문자[a-zA-Z]와 같다
[:blank:] 빈칸(space)이나 탭 문자([\t ])와 같다
[:cntrl:] 아스키 제어문자(아스키 0번부터 31, 127번)
[:digit:] 모든 한 자리 숫자([0-9]와 같다)
[:graph:] [:print:]와 동일하나 빈칸(space)은 제외
[:lower:] 모든 소문자([a-z]와 같다)
[:print:] 출력 가능한 모든 문자
[:punct:] [:alnum:]이나 [:cntrl:]가 포함되지 않은 모든 문자
[:space:] 빈칸을 포함한 모든 공백 문자[\f\n\r\t\v]와 같다
[:upper:] 모든 대문자[A-Z]와 같다
[:xdigit:] 모든 16진수 숫자[a-fA-F0-9]와 같다


예문

<BODY BGCOLOR="#336633" TEXT="#FFFFFF"

MARGINWIDTH="0" MARGINHEIGHT="0"

TOPMARGIN="0" LEFTMARGIN="0">

 

정규표현식

#[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]

 

결과

<BODY BGCOLOR="#336633" TEXT="#FFFFFF"

MARGINWIDTH="0" MARGINHEIGHT="0"

TOPMARGIN="0" LEFTMARGIN="0">

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
void input();
string words;
int main() {
    input();
    cout << words << endl;
    cout << "---------------------------------" << endl;
    regex re(R"(#[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]])");
    smatch match;
    while (regex_search(words, match, re)) {
        cout << match[0<< endl;
        words = match.suffix();
    }
}
cs

 

 

 

 

 

앞서 사용한 패턴에서는 [0-9A-Fa-f]를 여섯번 반복했고 

[0-9A-Fa-f] 는 [[:xdigit:]]를 대체하며 둘은 똑습니다.

 

하지만 

[[:xdigit:]]를 6번이나 사용하는건 매우 비효율적입니다.

다음엔 반복을 통해서 [[:xdigit:]]를 6번 쓰는것을 어떻게 줄이는지 알아보고자 합니다

 

지금까지 읽어주셔서 감사합니다

궁금한점 혹은 모르는점 어떤 질문이든 댓글은 언제나 환영입니다.

공감도 눌러주실꺼죠???