c 正则表达式

c 正则表达式

参考教程:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md

在linux下主要有三个函数,用于正则表达式

#include <sys/types.h>
#include <regex.h>

//生成规则
int regcomp(regex_t *preg, const char *regex, int cflags);

//要匹配的目标字符串
int regexec(const regex_t *preg, const char *string, size_t nmatch,
                   regmatch_t pmatch[], int eflags);

//释放内存
void regfree(regex_t *preg);

函数regcomp的参数cflags

  • REG_EXTENDED

    使用扩展的正则表达式语法。

    意思是,解释正则表达式时使用扩展的正则表达式语法。POSIX规范将正则表达式的实现方法分为了两种:基本正则表达式(BRE)和扩展正则表 达式(ERE)。

    BRE和ERE到底有什么区别?其实仅仅是元字符的不同!在BRE方式中,只承认^ 、$、 . 、[ 、] 、*这些是元字符,所有其他的字符都被识别为文字字符。而ERE中,则添加了(、 ) 、{ 、} 、?、 + |、等元字符(及其相关功能)。grep命令默认支持BRE,要想支持ERE需要使用-E选项。

  • REG_ICASE

    忽略大小写。

  • REG_NOSUB

    如果使用了这个选项得到的编译后的正则表达式,在被后面的regexec()函数使用时,regexec()的nmatch参数和pmatch参数将会被忽略 。

  • REG_NEWLINE

    其实REG_NEWLINE的作用就两个:

    1、 使^和$有效。

    2、 绝对不匹配换行符

函数regexec的参数eflags:还没弄明白

括号()的作用

假如有正则表达式【name=[^&]*】(目的是匹配URL里的name=xxx),如果匹配上了,则在pmatch里返回的是【name=xxx】,但是如果我还想要=号后面的xxx,怎么办呢?

那就加个括号,【name=([^&]*)】,这个正则表达式,匹配后,pmatch[0]里匹配的值是【name=xxx】,pmatch[1]里匹配的值则是【xxx】,这就是括号的妙用。

REG_NEWLINE的作用

假如有正则表达式【^age=[^&]*】(目的是匹配URL里的\r\n后面的name=xxx)。如果在调用regcomp是没有指定参数REG_NEWLINE,则目标字符串:【username=xdd\r\nage=22&husband=qinger\r\n&like=study&look=pretty\r\n 】无法被匹配;

加了REG_NEWLINE,【age=22】就被匹配出来了。

函数regexec的局限:匹配到一个后,即使后面还有,它也不去匹配了,也就是说只匹配一次。

那么,如果想匹配多次怎么办呢,手动改变目标字符串,把已经匹配完的切掉,用剩下的串在继续调用regexec函数,直到全部匹配完。提供个小例子,完成多次匹配。

原理:rm_eo返回的是匹配到的末尾位置,所以让新的串sbuf,指向上一次的末尾,再继续调用regexec,也就是每次都改变sbuf

/* 取子串的函数 */
static char* substr(const char*str, unsigned start, unsigned end)
{
    unsigned n = end - start;
    static char stbuf[256];
    strncpy(stbuf, str + start, n);
    stbuf[n] = 0;
    return stbuf;
}


size_t nmatch = 3;
regmatch_t pmatch[3];
const char* lbuf = "The fat cat. sat. on the mat.";
const char* sbuf = lbuf;

while(regexec(&reg, sbuf, nmatch, pmatch, 0) == 0){

  for (x = 0; x < nmatch && pmatch[x].rm_so != -1; ++x) {
    printf("    $%d='%s'\n", x, substr(sbuf, pmatch[x].rm_so, pmatch[x].rm_eo));

  }
  //rm_eo返回的是匹配到的末尾位置,所以让新的串,指向上一次的末尾,再继续调用regexec
  sbuf = &sbuf[pmatch[--x].rm_eo];
}

完整的小例子:

#include <stdio.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>

/* 取子串的函数 */
static char* substr(const char*str, unsigned start, unsigned end)
{
    unsigned n = end - start;
    static char stbuf[256];
    strncpy(stbuf, str + start, n);
    stbuf[n] = 0;
    return stbuf;
}

int main(){

  regex_t reg;

  int ret = regcomp(&reg, "(at\\.)$", REG_NEWLINE | REG_EXTENDED);
  if(ret != 0){
    printf("regcomp error %d\n", ret);
    return 1;
  }


  size_t nmatch = 3;
  regmatch_t pmatch[3];
  const char* lbuf = "The fat cat. sat. on the mat.";
  const char* sbuf = lbuf;
  int x = 0;

  while(regexec(&reg, sbuf, nmatch, pmatch, 0) == 0){

    for (x = 0; x < nmatch && pmatch[x].rm_so != -1; ++x) {
      printf("    $%d='%s'\n", x, substr(sbuf, pmatch[x].rm_so, pmatch[x].rm_eo));

    }
    sbuf = &sbuf[pmatch[--x].rm_eo];
  }



  regfree(&reg);
}  

参考:https://www.cnblogs.com/qingergege/p/7359935.html

c/c++ 学习互助QQ群:877684253

1414315-20181106214320230-961379709.jpg

本人微信:xiaoshitou5854

转载于:https://www.cnblogs.com/xiaoshiwang/p/11493201.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值