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(®);
}
參考:https://www.cnblogs.com/qingergege/p/7359935.html