我们都知道标准的C和C++都不支持正则表达式,但有一些函数库可以辅助C/C++程序员完成这
一功能,其中最著名的当数Philip Hazel的Perl-Compatible Regular
Expression库,许多Linux发行版本都带有这个函数库。
如果你想查看的话,你只需要输入 man regcomp,然后打开你的金山词霸作为配合即可
编译正则表达式
据说目的是为了提高执行效率才这么干的,把你的正则式先给编了,在把编完了的正则式和你想分析或查找的字符串去匹配
int regcomp (regex_t *compiled, const char *pattern, int cflags)
功能说明:把pattern编译后才存到compiled中,成功编译返回0,否则,非0
参数说明:
regex_t 是一个结构体数据类型,用来存放编译后的规则表达式,它的成员re_nsub 用来存储规则表达式中的子规则表达式的个数,子规则表达式就是用圆括号包起来的部分表达式。
pattern 是指向我们写好的规则表达式的指针。
cflags 有如下4个值或者是它们或运算(|)后的值:
REG_EXTENDED 以功能更加强大的扩展规则表达式的方式进行匹配。
REG_ICASE 匹配字母时忽略大小写。
REG_NOSUB 不用存储匹配后的结果。
REG_NEWLINE 识别换行符,这样'$'就可以从行尾开始匹配,'^'就可以从行的开头开始匹配
匹配正则表达式
用regcomp()函数成功地编译了正则表达式,接下来就可以调用regexec()函
数完成模式匹配:
int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int eflags)
功能说明:把你要分析或查找的字符串和存放编译好的正则式的preg进行匹配,成功编译返回0,否则,非0
当我们编译好规则表达式后,就可以用regexec 匹配我们的目标文本串了,如果在编译规则表达式的时候没有指定cflags的参数为REG_NEWLINE,则默认情况下是忽略换行符的,也就是把整个文本串当作一个字符串处理。执行成功返回0。
参数说明:
regmatch_t 是一个结构体数据类型,成员rm_so 存放匹配文本串在目标串中的开始位置,rm_eo 存放结束位置。通常我们以数组的形式定义一组这样的结构。因为往往我们的规则表达式中还包含子规则表达式。数组0单元存放主规则表达式位置,后边的单元依次存放子规则表达式位置。
compiled 是已经用regcomp函数编译好的规则表达式。
string 是目标文本串。
nmatch 是regmatch_t结构体数组的长度。
matchptr regmatch_t类型的结构体数组,存放匹配文本串的位置信息。
eflags 有两个值
REG_NOTBOL 我到现在还不是很明白这个参数的意义,可以参考Linux下的原文
释放正则表达式
无论什么时候,当不再需要已经编译过的正则表达式时,最好应该调用函数
regfree()将其释放,以免产生内存泄漏。在Linux原文中也没去强调的很清楚
void regfree(regex_t *preg);
参数说明:
preg:一个指向regex_t数据类型的指针
功能说明:
释放编译好了的正则表达式,防止产生内存泄露
报告错误信息
如果调用函数regcomp()或regexec()得到的是一个非0的返回值,则表明在对正则
表达式的处理过程中出现了某种错误,此时可以通过调用函数regerror()得到详
细的错误信息。
size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)
功能说明:
当执行regcomp 或者regexec 产生错误的时候,就可以调用这个函数而返回一个包含错误信息的字符串。
参数说明:
errcode 是由regcomp 和 regexec 函数返回的错误代号。
compiled 是已经用regcomp函数编译好的规则表达式,这个值可以为NULL。
buffer 指向用来存放错误信息的字符串的内存空间。
length 指明buffer的长度,如果这个错误信息的长度大于这个值,则regerror 函数会自动截断超出的字符串,但他仍然会返回完整的字符串的长度。所以我们可以用如下的方法先得到错误字符串的长度。
size_t length = regerror (errcode, compiled, NULL, 0);
下面是我的一个例子:
#include
#include
#include
#include
#include
#include
char *zz="i$"; //regular expression for testing
int main(){
FILE* fp = NULL;
char msg[1000] = {0};
//for regular expression
char ebuf[128];//save regular expression's error
regex_t *reg; //a struct to save the result of bulid the regular expression
int z;
regmatch_t pm[10];
const size_t nmatch = 10;
int x;
int lno;
//end
int n;
fp = fopen("1", "r+");
if(fp == NULL){
perror("fopen return error\n");
exit(1);
}
//get the log
while(fgets(msg, sizeof(msg), fp)){
if(msg[0] == '#' || msg[0] == '\n')
continue;
if(strlen(msg) <1)
continue;
if(msg[strlen(msg)-1] == '\n'){
msg[strlen(msg)-1] = '\0';
}
if(msg[strlen(msg)-2] == '\r'){
msg[strlen(msg)-1] = '\0';
}
printf("The msg:%s\n",msg);
//analysis msg
//bulid
if ((z=regcomp(reg, zz, REG_NEWLINE)) != 0)
{
regerror(z, reg, ebuf, sizeof(ebuf));
fprintf(stderr, "%s: zz '%s' \n",ebuf, zz);
}
//analysis
z = regexec(reg, msg, nmatch, pm, 0);
if (z != 0) {
printf("**********\n");
memset(msg, 0, sizeof(msg));
regfree(reg);
continue;
}
else{
printf("The msg who match the regular expression is: %s\n",msg);
regfree(reg);
}//end else
memset(msg, 0, sizeof(msg));
}//end while
fclose(fp);
return 0;
}
我匹配的是所有以i结尾的字符串,待匹配的源字符串我是给放在一个文件中,存放字符串的文件为
当前目录下的1,你也可以自己在你的当前目录下建个1,并且在1里面写上你要分析的字符串信息,甚至你可以直接给出字符串让你的正则式来分析。总之,找到你喜欢的方式,享受编程的快感
Enjoy programming,enjoy Linux,enjoy CU,and enjoy your life!