정규 표현식
여기서는 Lex n' Yacc을 하다보니 필요하게 된 정규표현식에 대해 서술합니다.
다양한 곳에 활용되는것이니 언젠가 또 쓸데가 있겠지.
학습 기록
'.': 아무나 한글자를 매칭시킴을 일컬음.
'\d', '\D' : 숫자 , 비 숫자 매칭.
'\s', '\S' : 공백 , 비 공백 문자 매칭. 이때 공백문자는 : '\t', '\f', '\r', '\n' 이 있음.
'\w', '\W' : 글자 , 비 글자 문자 매칭.
^(문자) : 해당 문자로 반드시 시작해야 한다.
(문자)$ : 해당 문자로 반드시 끝나야 한다.
문자 클래스 [] : 해당 문자를 묶어서 하나의 형태로 인정한다. 예를 들면, [aeiou] is vowel → “a is vowel”, 또는 “u is vowel” 로 인정.
문자 클래스 내의 '^' 표시는 '부정'을 일컫는다. 즉, [^aeiou] is not vowel → “k is not vowel” 과 같은 형태로 매칭함.
문자클래스에서 [A-Z] 와 같은 형태로 여러 문자를 한번에 표시할 수 있다.
[A-Z] / [a-z] 대문자 및 소문자.
[0-9] 숫자.
{x, y} 표현 : 패턴의 반복횟수 등을 지정할 수 있다.
w{3,5} : 글자 w 가 3~5회 반복되는 것에 매칭.
[xyz]{5,} : x,y 또는 z 가 5회 이상 반복되는 것에 매칭.
\d{1, 4} : 숫자 1~4 글자에 매칭.
'*' : 앞의 문자와 0회 부터 무한대 까지 매칭되면 인정. 예를 들어, 'A*s'면, 's'도 인정, “AAAAAAAs” 도 인정.
'+' : 앞의 문제와 1회 부터 무한대 까지 매칭되면 인정. 위의 것을 알면 잘 알겠지.
\b : “boundary” 즉, 'cat' 을 골라내고 싶다고 할때, '\bcat\b' 이라 한다면, 'Acat'은 안되고, 'A cat'은 되는 뭐 그런거.
() 소괄호 : 정규식의 '그룹화'를 가능하게 함. 정확하게는, 괄호 내의 정규식 연산이 우선하도록 한다. 'Quantifier;수량사'와 함께 사용하는 경우가 많다고 서술되어 있음.
1)
| : '선택'이 가능하다. 즉, 'abc|ABC|xyZ' 상황에서는 abc, ABC, xyZ에 모두 매칭한다.
? : (위키에 의하면) 0/1회 발생에 대해 매칭을 수행함. 예를 들어서, colou?r 이면, color, colour에 매칭하는 듯.
(?⇐regex_2)regex_1 : regex_2 이후에 regex_1에 부합하는 매칭을 찾아주지만, 매칭 결과로 regex_2에 해당하는 내용은 제외된다. 그러니까, (?⇐[a-z])[aeiou]라 한다면, 'or' 에는 매칭 안하고, 'rob'에 대해 매칭은 하지만 실제로 매칭한 string은 o 만 되는 셈.
(?<!regex_2)regex_1 : 위의 내용과 반대로, regex_2에 해당되지 않는 내용 이후에 regex_1에 부합하는 매칭을 찾는다.
regex_1(?=regex_2) : regex_2 이전에 regex_1에 부합하는 매칭을 찾아주지만, regex_2에 해당되는 내용은 제외한다. 그러니까, c(?=o)하면, clevlanco가 매칭되는 것.
regex_1(?!regex_2) : 위의 내용과 반대로, regex_2에 부합되지 않는 내용 이전에 regex_1에 부합하는 매칭을 찾는다.
\1 : groupnumber를 매겨서 써먹을 수 있다. \1, \2, \3등등.. 예를들어서, (\w)(\w)(\w)a\3\2\1은, xyzazyx 와 매칭한다. 대신 그룹으로 선언된 영역에서 매칭된 글자와 같은 글자가 매칭되는 것이 특징.
Backward group reference : 이를 응용하면, 12-34-56-78 또는 12345678을 매칭하고 싶을때, \d\d(-?)\d\d\1\d\d\1\d\d 로 써먹으면 두 경우에 모두 매칭시킬 수 있음.
(?|(regex)|(regex)…)
2) : (regex|regex)와 비슷하게 써먹을 수도 있겠지만, catured 된 결과가 달라지게 된다고 한다… 당최 무슨의미인지 참… 각주 참고. ()group 내에 group을 다시 명시해야 하는 것에 주의할것. 아! 그러니까, 1그룹화 하는것과 같다. 저것을 하나의 group으로 묶어주는 효과가 있음. 이를 통해 $1하나만 반환하도록 한다고 한다.
주의 : 이건 Perl/PHP/R/Delphi에서만 지원한다!
forward group reference : 뒤에 나오는 Group을 '앞에'사용할 때 유용하다. group내에 group의 반복적 사용을 명시할 때만 유용하다.
아 젠장맞을 겁나 어렵네
이를 이용해서 C 언어에서 정규표현식을 써먹을 때.
POSIX 라이브러리 헤더인 regex.h를 통해 다음의 함수 인터페이스를 제공한다.
#include <regex.h>
int regcomp(regex_t *restrict preg, const char *restrict pattern, int cflags);
size_t regerror(int errcode, const regex_t *restrict preg, char *restrict errbuf, size_t errbuf_size);
int regexec(const regex_t *restrict preg, const char *restrict string, size_t nmatch, regmatch_t pmatch[restrict], int eflags);
void regfree(regex_t *preg);
예제를 다음과 같이 써먹고 어떻게 써먹는지는 나중에 서술.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <regex.h>
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int line = 0;
regex_t state;
regmatch_t matched[2];
int ret;
int status;
char str[1024];
const char *pattern ="a href=\"[a-zA-Z|/|_|:]+";
if(regcomp(&state, pattern, REG_EXTENDED)) return -1;
fscanf(stdin,"%d\n", &line);
for(int i = 0; i<line; i++){
//fscanf(stdin, "%s", &str);
fgets(str, 1024, stdin);
ret = regexec(&state, str, 2, matched, 0);
if(ret==0)
fprintf(stdout, "matched pattern string : %.*s... \n", matched[0].rm_eo- matched[0].rm_so, &str[matched[0].rm_so]);
fprintf(stdout, "origin %s: %d\n", str, ret);
//fprintf(stdout, "%s", str);
}
return 0;
}
깊이 찾아볼 것?