正規表現文字列処理ライブラリ reglib.c

POSIX準拠のregex.hを用いて、正規表現による文字列処理のためのライブラリを作ってみました。ただし、今後仕様を大幅に変更する予定なので、配布はしていません。必要な方は掲載しているソースコードを参考にしてください。

Cでの正規表現の使い方に関しては、POSIX正規表現 regex.h の使用方法を参照してください。

ヘッダファイル

reglib.cでは以下のヘッダファイルを使用しています。reglib.cを使用するには、文字列処理ライブラリautostring.cが必要です。reglib.hは関数のプロトタイプ宣言を行っているだけなので、内容は割愛します。

#include <unistd.h>
#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "reglib.h"
#include "autostring.h"

ライブラリ関数群

regsplit()

正規表現によるパターンの前までの文字列を切り出す。

/* 文字列str、正規表現パターンregex、 */
/* マッチした部分文字列バッファ用ポインタを渡すと、 */
/* 文字列を正規表現パターンの前までのものにすることができる。 */
/* マッチした部分文字列の終わりの次の文字から始まる文字列への */
/* ポインタを返す。 */
char* regsplit(char* str,const char* regex,char** matched_str,int cflags)
{
    size_t reglen; /* マッチした文字列の長さ */
    int regsuccess; /* パターンマッチングの成功フラグ */
    regex_t reg; /* regexパターンバッファ */
    regmatch_t match; /* マッチした場所格納用 */

    regcomp(&reg,regex,cflags);
    regsuccess = regexec(&reg,str,1,&match,0);
    regfree(&reg);

    if(regsuccess == REG_NOMATCH) return NULL;

    reglen = match.rm_eo - match.rm_so;
    *matched_str = (char*)malloc(reglen+1);
    if(*matched_str == NULL) return NULL;

    **matched_str = '\0';
    strncat(*matched_str,&str[match.rm_so],reglen);

    str[match.rm_so] = '\0';
    return &str[match.rm_eo];
}

regreplace()

正規表現によるパターンの文字列を置換する。

/* 文字列strの先頭を示すポインタのアドレス、正規表現パターン、 */
/* 置換後の文字列を渡す。 */
/* 置換後の文字列中の"%_"は、マッチした部分文字列を表す。 */
/* 置換後の文字列で"%_"自体に置き換えたい場合は…どうするかね? */
char* regreplace(char** str,const char* regex,const char* after,int cflags)
{
    const size_t ini_len = strlen(*str);
    char* tail,*matched_str;
    char* temp_aft = strmirror(after);
    char* temp_buf = strmirror(*str);
    if(temp_buf==NULL || temp_aft==NULL) return NULL;

    tail = regsplit(temp_buf,regex,&matched_str,cflags);
    if(tail == NULL) return NULL;

    allreplace(&temp_aft,"%_",matched_str);
    *str = (char*)realloc(*str,ini_len + strlen(temp_aft) + 1);

    sprintf(*str,"%s%s%s",temp_buf,temp_aft,tail);
    free(temp_aft);
    free(temp_buf);

    free(matched_str);
    return *str;
}

使用例

regreplace(&str,"http://[[:alnum:]./~?&%#_=-]+",
    "<a href=\"%_\">%_</a>",REG_EXTENDED);

regrpall()

正規表現によってマッチした文字列をすべて置換する。

char* regrpall(char** str,const char* regex,const char* after,int cflags)
{
    char* form,*latt;
    char* mat_str;
    char* temp_buf = strmirror(*str);
    char* temp_aft = strmirror(after);

    if(temp_buf==NULL || temp_aft==NULL) return NULL;

    strcpy(*str,""); /* 文字列をクリア */

    for(form=temp_buf ;
    (latt=regsplit(form,regex,&mat_str,cflags)) != NULL ; form=latt){
        allreplace(&temp_aft,"%_",mat_str);
        *str = strplus(str,form);
        *str = strplus(str,temp_aft);

        free(temp_aft);
        temp_aft = strmirror(after);
        free(mat_str);
    }
    *str = strplus(str,form);

    free(temp_aft);
    free(temp_buf);
    return *str;
}

regcnt()

文字列中に含まれる正規表現パターンを数える。パターンにマッチした部分文字列の数を返す。

int regcnt(const char* str,const char* regex,int cflags)
{
    int regcount=0; /* パターンマッチングの成功数 */
    const char* regpoint=str; /* パターンを探す文字列のスタート地点 */
    regex_t reg; /* regexパターンバッファ */
    regmatch_t match; /* マッチした場所格納用 */

    regcomp(&reg,regex,REG_EXTENDED);

    while(regexec(&reg,regpoint,1,&match,0)!=REG_NOMATCH){
        regcount++;
        regpoint = &regpoint[match.rm_eo];
    }

    regfree(&reg);
    return regcount;
}


Index Page