Skip to content

[c] pcre2 sample code

Myungchul Shin edited this page Oct 21, 2016 · 16 revisions
#ifdef __cplusplus
extern "C" {
#endif

#ifndef PCRE_H
#define PCRE_H

#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

#define PCRE_VAL_SIZE   1024

pcre2_code* build_pcre(char* regs_file);
void        destroy_pcre(pcre2_code* re);
void        match_pcre(pcre2_code* re, char* string);

#endif

#ifdef __cplusplus
}
#endif
  • pcre.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pcre.h"


/* -------------------------------------------------------------------------
 * private functions
 * ------------------------------------------------------------------------- */

static char* read_regs(char* regs_file)
{
    int             size;
    char            string[PCRE_VAL_SIZE+1];
    int             cnt_line;
    FILE*           fp;
    char*           pattern;
    int             capa = PCRE_VAL_SIZE;
    int             limit = PCRE_VAL_SIZE;
    char*           realloc_ptr;

    fp = fopen(regs_file, "r");
    if( !fp ) {
        fprintf(stderr,"file open error : %s\n", regs_file);
        return NULL;
    }
    pattern = malloc(sizeof(char)*PCRE_VAL_SIZE+10);
    if( !pattern ) {
        fprintf(stderr,"malloc fail\n");
        return NULL;
    }

    *pattern = '\0';

    cnt_line = 0;
    while(fgets(string, PCRE_VAL_SIZE, fp) != NULL) {
        size = strlen(string);
        if(string[size-1] == '\n'){
            string[size-1] = '\0';
            --size;
        }
        if(size > 1 && string[size-1] == '\r'){
            string[size-1] = '\0';
            --size;
        }
        if(string[0] == '\0')
            continue;

        // re-sizing
        if( limit - size <= 100 ) {
            capa = capa * 2;
            limit = capa + limit;
            realloc_ptr = realloc(pattern, capa * 2);
            if( !realloc_ptr ) {
                fprintf(stderr,"realloc fail\n");
                return NULL;
            }
            pattern = realloc_ptr;
        }

        if(cnt_line==0) {
            strcat(pattern, string);
            limit -= strlen(string);
        } else {
            strcat(pattern, "|");
            limit -= 1;
            strcat(pattern, string);
            limit -= strlen(string);
        }

        cnt_line++;
    }

    fclose(fp);
    return pattern;

}

/* -------------------------------------------------------------------------
 * public functions
 * ------------------------------------------------------------------------- */

pcre2_code* build_pcre(char* regs_file)
{
    pcre2_code*         re;
    char*               pattern;
    PCRE2_SIZE          erroffset;
    int                 errorcode;
    PCRE2_UCHAR8        buffer[120];

    pattern = read_regs(regs_file);
    if( !pattern ) {
        return NULL;
    }

    re = pcre2_compile((PCRE2_SPTR)pattern, -1, PCRE2_UTF, &errorcode, &erroffset, NULL);
    if ( re == NULL ) {
        (void)pcre2_get_error_message(errorcode, buffer, 120);
        fprintf(stderr,"%d\t%s\n", errorcode, buffer);
        return NULL;
    }

    if( pattern ) free(pattern);
    return re;
}

void destroy_pcre(pcre2_code* re)
{
    if( re ) {
        pcre2_code_free(re);
    }
}

void match_pcre(pcre2_code* re, char* string)
{
    pcre2_match_data*   match_data;
    PCRE2_SIZE*         ovector;
    int                 rc;
    int                 i;
    int                 begin;
    int                 len;
    char                chr;

    fprintf(stdout, "%s\n", string);
    match_data = pcre2_match_data_create(3*10, NULL);
    rc = pcre2_match(re, (PCRE2_SPTR)string, -1, 0, 0, match_data, NULL);
    if( rc > 0 ) {
        ovector = pcre2_get_ovector_pointer(match_data);
        for(i = 0; i < rc; i++) {
            begin = ovector[2*i];
            len   = ovector[2*i+1] - ovector[2*i];
            chr = string[begin+len];
            string[begin+len] = '\0';
            fprintf(stdout, "%d\t%d\t%d\t%s\n", i, begin, begin+len, &string[begin]);
            string[begin+len] = chr;
        }
    }
    fprintf(stdout, "\n");
    pcre2_match_data_free(match_data);
}
  • test_pcre.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>

#include "pcre.h"

#define LINE_SIZE       10240

int main(int    argc, char  *argv[])
{
    int                 size;
    char                string[LINE_SIZE+1];
    int                 cnt_line;
    pcre2_code*         re;

    struct timeval t1,t2;

    if(argc != 2) {
        fprintf(stderr,"%s <regs file>\n",argv[0]);
        exit(1);
    }

    re = build_pcre(argv[1]);
    if( !re ) return 1;

    gettimeofday(&t1, NULL);

    cnt_line = 0;
    while(fgets(string, LINE_SIZE, stdin) != NULL) {
        size = strlen(string);
        if(string[size-1] == '\n'){
            string[size-1] = '\0';
            --size;
        }
        if(size > 1 && string[size-1] == '\r'){
            string[size-1] = '\0';
            --size;
        }
        if(string[0] == '\0')
            continue;

        match_pcre(re, string);

        cnt_line++;
    }

    gettimeofday(&t2, NULL);
    fprintf(stderr,"elapsed time = %lf sec\n",((t2.tv_sec - t1.tv_sec)*1000000 + t2.tv_usec - t1.tv_usec)/(double)1000000);

    destroy_pcre(re);

    return 0;

}
  • regular expression file
\d+개월
\d+명
\d+일
[월년]{0,1}\s*\d+만[원명]{0,1}
\d+억[원]{0,1}
\d+년[간]{0,1}
\d+년[도]{0,1}
\d+\s*/\s*\d+\s*/\s*d+
분당\s*\d+\s*-\s*\d+발
\d+[.]{0,1}\d*kg\s*[~-]\d+[.]{0,1}\d*kg
밤\s*\d+\s*~\s*새벽\s*\d+시
만\s*\d+세
utc\s*-\s*\d[\d:]*
  • i'd compared the output of pcre2 sample program to the output of cre2
    • example

터키 외무장관인 압둘라 굴은 “터키가 조직적인 테러리스트들의 공격에 직면했다”고 밝혔다. 터키 연정 소속 모국당(mp)지도자인 메수트 일마즈 부총리는 9일 tv연설을 통해 "에체비트 총리의 건강문제가 정치위기의 원인"이라며 조기 총선 실시를 요구했다.그는 오는 12월 시작될 유럽연합(eu)가입협상을 위해 새 정부를 구성해야한다고 주장했다.집권 연정 지도자가 공개적으로 조기 총선을 요구한 것은 이번이 처음이며 다음 총선은 2004년 4월로 예정돼있었다.터키 에너지.천연자원부는 바쿠-트빌리시-케이한(btc) 원유 송유관과 바쿠 -트빌리시-에르주룸(bte) 천연가스 송>유관 건설 공사가 예정 기한내에 완공될 것이 라고 밝혔다. 터키 앙카라 소재의 중동공과대학의 연구진은 30명의 아마추어 축구 선수들과 축구를 하지 않는 일반인을 대상으로 x-선과 자기공명영상장치(mri) 촬영을 실시한 결과, 운동선수들의 목은 일반인보다 유연성이 떨어지고 척추 맨 위쪽 목 부위의 디스크는 움직임이 심하고 손상정도가 큰 것으로 나타났다고 '뉴사이어티스트'지에 보고했다.터키 앙카라 대학의 연구진이 호르몬 변화가 여성의 몸이나 입맛 에 어떤 영향을 미치는지 알아보기 위해 폐경이 지난 60대 여성 20명과 같은 나이의 남성 20명에게 단맛, 짠맛, >쓴맛, 신맛을 각 각 맛보게 한 결과, 다른 맛은 여성과 남성 모두 비슷한 것에 반 해 단맛은 여성이 덜 인지하는 경향을 보였다. 터키 물고기, 피부병에 탁월한 효능 ..터키 등 주한 외국 공관에 대한 경비를 강화한데 이어 이라크 파병국 공관에 대한 순찰도 강화해왔습니다. 터키 등 이슬람 국가들은 파병 결정을 철회하고 있는데.터키 당국과 건축업자들은 부실한 건축물 관리와 허>술한 공사로 인한 비판과 책임을 피해가기 어렵게 됐습니다.

  • cre2 0 208 212 9일 1 356 361 12월 2 577 589 2004년 4월 3 899 904 30명 4 1454 1459 20명 5 1487 1492 20명

  • pcre2 0 208 212 9일

    - it seems something weired 
    - it's because pcre2 always provide first match(return) and not provide longest match 
    

    regs = \d+분|\d+월|\d+명|\d+일|\d+년|\d+년\s*\d+월\s*\d+일 string = '2005년 4월 10일' match = '2005년'

    regs = \d+년\s*\d+월\s*\d+일|\d+분|\d+월|\d+명|\d+일|\d+년 string = '2005년 4월 10일' match = '2005년 4월 10일'

    - you can test pcre2 regular expression match [here](https://regex101.com/)
    - how to resolve this problem?
      - first, repeat matching at the end of previous matching position
      - second, use POSIX regexec() for longest match 
    
    
  • other library

Clone this wiki locally