• 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里的 后面的name=xxx)。如果在调用regcomp是没有指定参数REG_NEWLINE,则目标字符串:【username=xdd age=22&husband=qinger &like=study&look=pretty 】无法被匹配;

    加了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'
    ", 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
    ", 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'
    ", 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

    本人微信:xiaoshitou5854

  • 相关阅读:
    [转] JavaScript中的字符串操作
    关于多线程学习的笔记
    [转] jquery 使用方法
    ubuntu下安装tomcat和配置mysql
    [转] 使用CodeViz生成C/C++函数调用关系图
    [转] java中的匿名内部类总结
    [转] Java中继承thread类与实现Runnable接口的区别
    字符串 指针、调试---师傅传授 栈中指针地址 与 堆中数据地址 标准写法
    maven 阿里云节点,速度快
    解决IntelliJ IDEA 创建Maven项目速度慢问题 DarchetypeCatalog
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/11493201.html
Copyright © 2020-2023  润新知