사용자 도구

사이트 도구


정규표현식

정규 표현식

여기서는 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;
}

깊이 찾아볼 것?

  • [a-zA-Z]와 \w 의 차이를 알아 볼 것.
  • matching 과 capture의 개념을 이해하고 넘어가면 좋음.
정규표현식.txt · 마지막으로 수정됨: 2017/08/19 22:13 (바깥 편집)