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(®, 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(®, "(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(®, 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(®); }
参考:
c/c++ 学习互助qq群:877684253
本人微信:xiaoshitou5854