Linux C 支持正则表达式的字符串替换函数

 
root@localhost src]# cat a.c
/**
* Linux C 支持正则表达式的字符串替换函数
*
* 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函数的返回类型
typedef struct _reg_rtn_struct
{
   int rtn;       //成功与否标志0 成功, 1失败
   int pstart;    //匹配到的子串开始位移
   int pend;      //匹配到的子串尾部位移
} reg_rtn_struct;


/**
*
* 正则表达式查找函数
*/
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[]

    //编译正则表达式
    /**
     *
     * @param const char*  pattern         将要被编译的正则表达式
     * @param regex_t*     reg             用来保存编译结果
     * @param int          cflags          决定正则表达式将如何被处理的细节
     *
     * @return  success    int        0    并把编译结果填充到reg结构中
     *          fail       int        非0
     *
     */


    z = regcomp(&reg, (const char*)pattern, cflags);

    if(z != 0)
    {
       regerror(z, &reg, 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(&reg);
       return reg_rtn_struct_var;
    }

    /**
     *
     * reg     指向编译后的正则表达式
     * str     指向将要进行匹配的字符串
     * pm      str字符串中可能有多处和正则表达式相匹配, pm数组用来保存这些位置
     * nmacth  指定pm数组最多可以存放的匹配位置数
     *
     * @return 函数匹配成功后,str+pm[0].rm_so到str+pm[0].rm_eo是第一个匹配的子串
     *                           str+pm[1].rm_so到str+pm[1].rm_eo是第二个匹配的子串
     *                           ....
     */
    z = regexec(&reg, str, nmatch, pm, 0);

    //没有找到匹配数据
    if(z == REG_NOMATCH)
    {
       reg_rtn_struct_var.rtn    = 1;
       reg_rtn_struct_var.pstart = -1;
       reg_rtn_struct_var.pend   = -1;

       regfree(&reg);
       return reg_rtn_struct_var;
    }
    else if(z != 0)
    {
       perror("reg3");
       regerror(z, &reg, 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(&reg);

       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(&reg);
    return reg_rtn_struct_var;
}


/*
* 正则表达式替换函数
*/
char *cns_str_ereplace(char *src, const char *pattern, const char *newsubstr)
{
    //如果pattern和newsubstr串相等,则直接返回
    if(strcmp(pattern, newsubstr)==0)
       return src;

    //定义cns_reg的返回类型结构变量
    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


    //把源串预dest
    char *dest=src;  //替换后生成的串指针
    char *pstr=src;  //当找到串时,pstr就指向子串后面的地址从而标识下一个要查找的源串

    //用于malloc的临时内存区
    char *tmp;
    char *new_tmp_str=dest;

    int new_tmp_str_len=0;  //new_tmp_str相对于dest地址开始处的长度


    //开始循环替换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内的前new_tmp_str_len+pstart个内存空间的数据,拷贝到arr
            strncpy(tmp, dest, new_tmp_str_len+pstart);

            //标识串结束
            tmp[new_tmp_str_len+pstart]='/0';

            //连接arr和newstr, 即把newstr附在arr尾部, 从而组成新串(或说字符数组)arr
            strcat(tmp, newsubstr);

            //把src中 从oldstr子串位置后的部分和arr连接在一起,组成新串arr
            strcat(tmp, new_tmp_str+pend);

            //把用malloc分配的内存,复制给指针dest
            dest = strdup(tmp);

            //释放malloc分配的内存空间
            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()
{
  //测试正则表达式
  char str[]="1love2love3love4love5love6love!";

  reg_rtn_struct reg_rtn_struct_var;

  char *newstr=cns_str_ereplace(str,".?.?ve","..");
  puts(newstr);

  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值