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"
正規表現によるパターンの前までの文字列を切り出す。
/* 文字列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(®,regex,cflags);
regsuccess = regexec(®,str,1,&match,0);
regfree(®);
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];
}
正規表現によるパターンの文字列を置換する。
/* 文字列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);
正規表現によってマッチした文字列をすべて置換する。
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;
}
文字列中に含まれる正規表現パターンを数える。パターンにマッチした部分文字列の数を返す。
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(®,regex,REG_EXTENDED);
while(regexec(®,regpoint,1,&match,0)!=REG_NOMATCH){
regcount++;
regpoint = ®point[match.rm_eo];
}
regfree(®);
return regcount;
}