[root@localhost src]# cat a.c/**
* Linux C 支持正則表達(dá)式的字符串替換函數(shù)
*
* Author: cnscn@163.com
* Homepage: www.cnscn.org 歡迎您到cns家園來,有好吃的招待喲
* Date: 2007-03-08 17:41
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
//regex
#include <regex.h>
//cns_reg函數(shù)的返回類型
typedef struct _reg_rtn_struct
{
int rtn; //成功與否標(biāo)志0 成功, 1失敗
int pstart; //匹配到的子串開始位移
int pend; //匹配到的子串尾部位移
} reg_rtn_struct;
/**
*
* 正則表達(dá)式查找函數(shù)
*/
reg_rtn_struct cns_reg(const char *str, const char *pattern)
{
reg_rtn_struct reg_rtn_struct_var;
int z; //status
int pos; //配置處的位置
int cflags = REG_EXTENDED; //compile flags
regex_t reg; //compiled regular expression
char ebuf[128]; //error buffer
bzero(ebuf, sizeof(ebuf));
regmatch_t pm[10]; //pattern matches 0-9
bzero(pm, sizeof(pm));
const size_t nmatch = 10; //The size of array pm[]
//編譯正則表達(dá)式
/**
*
* @param const char* pattern 將要被編譯的正則表達(dá)式
* @param regex_t* reg 用來保存編譯結(jié)果
* @param int cflags 決定正則表達(dá)式將如何被處理的細(xì)節(jié)
*
* @return success int 0 并把編譯結(jié)果填充到reg結(jié)構(gòu)中
* fail int 非0
*
*/
z = regcomp(®, (const char*)pattern, cflags);
if(z) //此處為 if(z != 0), 因?yàn)镃語言里0永遠(yuǎn)為非(False), 任何非0值都為真(True)
{
regerror(z, ®, ebuf, sizeof(ebuf));
perror("reg1");
fprintf(stderr, "%s: pattern '%s'\n", ebuf, pattern);
reg_rtn_struct_var.rtn = 1;
reg_rtn_struct_var.pstart = -1;
reg_rtn_struct_var.pend = -1;
regfree(®);
return reg_rtn_struct_var;
}
/**
*
* reg 指向編譯后的正則表達(dá)式
* str 指向?qū)⒁M(jìn)行匹配的字符串
* pm str字符串中可能有多處和正則表達(dá)式相匹配, pm數(shù)組用來保存這些位置
* nmacth 指定pm數(shù)組最多可以存放的匹配位置數(shù)
*
* @return 函數(shù)匹配成功后,str+pm[0].rm_so到str+pm[0].rm_eo是第一個(gè)匹配的子串
* str+pm[1].rm_so到str+pm[1].rm_eo是第二個(gè)匹配的子串
* ....
*/
z = regexec(®, str, nmatch, pm, 0);
//沒有找到匹配數(shù)據(jù)
if(z == REG_NOMATCH)
{
reg_rtn_struct_var.rtn = 1;
reg_rtn_struct_var.pstart = -1;
reg_rtn_struct_var.pend = -1;
regfree(®);
return reg_rtn_struct_var;
}
else if(z) //if(z !=0)
{
perror("reg3");
regerror(z, ®, ebuf, sizeof(ebuf));
fprintf(stderr, "%s: regcomp('%s')\n", ebuf, str);
reg_rtn_struct_var.rtn = 1;
reg_rtn_struct_var.pstart = -1;
reg_rtn_struct_var.pend = -1;
regfree(®);
return reg_rtn_struct_var;
}
/*列出匹配的位置*/
if(pm[0].rm_so != -1)
{
reg_rtn_struct_var.rtn = 0;
reg_rtn_struct_var.pstart = pm[0].rm_so;
reg_rtn_struct_var.pend = pm[0].rm_eo;
}
regfree(®);
return reg_rtn_struct_var;
}
/*
* 正則表達(dá)式替換函數(shù)
*/
char *cns_str_ereplace(char *src, const char *pattern, const char *newsubstr)
{
//如果pattern和newsubstr串相等,則直接返回
if(!strcmp(pattern, newsubstr)) //if(strcmp(pattern, newsubstr)==0)
return src;
//定義cns_reg的返回類型結(jié)構(gòu)變量
reg_rtn_struct reg_rtn_struct_var;
int rtn = 0; //reg_rtn_struct_var.rtn
int pstart = 0; //reg_rtn_struct_var.pstart
int pend = 0; //reg_rtn_struct_var.pend
//把源串預(yù)dest
char *dest=src; //替換后生成的串指針
char *pstr=src; //當(dāng)找到串時(shí),pstr就指向子串后面的地址從而標(biāo)識(shí)下一個(gè)要查找的源串
//用于malloc的臨時(shí)內(nèi)存區(qū)
char *tmp;
char *new_tmp_str=dest;
int new_tmp_str_len=0; //new_tmp_str相對(duì)于dest地址開始處的長度
//開始循環(huán)替換src串中符合pattern的子串為newstr
while(!rtn)
{
reg_rtn_struct_var=cns_reg(new_tmp_str, pattern);
rtn = reg_rtn_struct_var.rtn;
pstart = reg_rtn_struct_var.pstart;
pend = reg_rtn_struct_var.pend;
if(!rtn)
{
//分配新的空間: strlen(newstr):新串長 pend-pstart:舊串長
tmp=(char*)calloc(sizeof(char), strlen(dest)+strlen(newsubstr)-(pend-pstart)+1 );
//把src內(nèi)的前new_tmp_str_len+pstart個(gè)內(nèi)存空間的數(shù)據(jù),拷貝到arr
strncpy(tmp, dest, new_tmp_str_len+pstart);
//標(biāo)識(shí)串結(jié)束
tmp[new_tmp_str_len+pstart]='\0';
//連接arr和newstr, 即把newstr附在arr尾部, 從而組成新串(或說字符數(shù)組)arr
strcat(tmp, newsubstr);
//把src中 從oldstr子串位置后的部分和arr連接在一起,組成新串a(chǎn)rr
strcat(tmp, new_tmp_str+pend);
//把用malloc分配的內(nèi)存,復(fù)制給指針dest
dest = strdup(tmp);
//釋放malloc分配的內(nèi)存空間
free(tmp);
new_tmp_str_len = new_tmp_str_len + pstart + strlen(newsubstr);
new_tmp_str=dest+new_tmp_str_len;
}
}
return dest;
}
int main()
{
//測試正則表達(dá)式
char str[]="1love2love3love4love5love6love!";
reg_rtn_struct reg_rtn_struct_var;
char *newstr=cns_str_ereplace(str,".?.?ve","..");
puts(newstr);
return 0;
}
[root@localhost src]# gcc -g a.c -o a && ./a
_such_.._you_love_you_love_you_sir!
_such_.._you_.._you_love_you_sir!
_such_.._you_.._you_.._you_sir!
_such_.._you_.._you_.._you_sir!