分类:
2011-02-20 01:25:27
正则表达式,一般简称regex、regexp、re,广泛应用于grep、vim、sed等。 具体实现很多,比较常见的有regex和pcre。
regex,是posix接口,多数C标准库自带,Linux下通过/usr/include/regex.h或者man regex查看。
接口只有四个:regcomp、regexec、regerror、regfree
#include
#include
#include
#define SUBSLEN 10 /* 匹配子串的数量 */
#define EBUFLEN 128 /* 错误消息buffer长度 */
#define BUFLEN 1024 /* 匹配到的字符串buffer长度 */
int main()
{
size_t len;
regex_t re; /* 存储编译好的正则表达式,正则表达式在使用之前要经过编译 */
regmatch_t subs [SUBSLEN]; /* 存储匹配到的字符串位置 */
char matched [BUFLEN]; /* 存储匹配到的字符串 */
char errbuf [EBUFLEN]; /* 存储错误消息 */
int err, i;
char src [] = "111
char pattern [] = "
printf("String : %s\n", src);
printf("Pattern: \"%s\"\n", pattern);
/* 编译正则表达式 */
err = regcomp(&re, pattern, REG_EXTENDED);
if (err)
{
len = regerror(err, &re, errbuf, sizeof(errbuf));
printf("error: regcomp: %s\n", errbuf);
return 1;
}
printf("Total has subexpression: %d\n", re.re_nsub);
/* 执行模式匹配 */
err = regexec(&re, src, (size_t) SUBSLEN, subs, 0);
if (err == REG_NOMATCH)
{ /* 没有匹配成功 */
printf("Sorry, no match ...\n");
regfree(&re);
return 0;
}
else if (err)
{ /* 其它错误 */
len = regerror(err, &re, errbuf, sizeof(errbuf));
printf("error: regexec: %s\n", errbuf);
return 1;
}
/* 如果不是REG_NOMATCH并且没有其它错误,则模式匹配上 */
printf("\nOK, has matched ...\n\n");
for (i = 0; i <= re.re_nsub; i++)
{
len = subs[i].rm_eo - subs[i].rm_so;
if (i == 0)
{
printf ("begin: %d, len = %d ", subs[i].rm_so, len); /* 注释1 */
}
else
{
printf("subexpression %d begin: %d, len = %d ", i, subs[i].rm_so, len);
}
memcpy (matched, src + subs[i].rm_so, len);
matched[len] = '\0';
printf("match: %s\n", matched);
}
regfree(&re); /* 用完了别忘了释放 */
return (0);
}
执行结果是
CODE:String : 111
从示例程序可以看出,使用之前先用regcomp()编译一下,然后调用regexec()进行实际匹配。如果只是看有没有匹配成功,掌握这2个函数的用法即可。
有时候我们想要取得匹配后的子表达式,比如示例中想获得title是什么,需要用小括号 "( )"把子表达式括起来"
pcre(Perl Compatible Regular Exprssions),有完善的使用说明和示例代码。
接口很多,常用的有:pcre_compile()、pcre_study()、pcre_exec()、pcre_free()。
将上面的regex代码修改如下:
#include
#include
#include
#define OVECCOUNT 30 /* should be a multiple of 3 */
#define EBUFLEN 128
#define BUFLEN 1024
int main()
{
pcre *re;
const char *error;
int erroffset;
int ovector[OVECCOUNT];
int rc, i;
char src [] = "111
char pattern [] = "
printf("String : %s\n", src);
printf("Pattern: \"%s\"\n", pattern);
re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
if (re == NULL)
{
printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
return 1;
}
rc = pcre_exec(re, NULL, src, strlen(src), 0, 0, ovector, OVECCOUNT);
if (rc < 0)
{
if (rc == PCRE_ERROR_NOMATCH)
printf("Sorry, no match ...\n");
else
printf("Matching error %d\n", rc);
free(re);
return 1;
}
printf("\nOK, has matched ...\n\n");
for (i = 0; i < rc; i++)
{
char *substring_start = src + ovector[2*i];
int substring_length = ovector[2*i+1] - ovector[2*i];
printf("%2d: %.*s\n", i, substring_length, substring_start);
}
free(re);
return 0;
}
执行结果是:
CODE:String : 111
pcre_study,可以加速匹配;如果编译之后多次使用,可以使用该功能。
pcre_compile()有很多选项,详细说明参见。
如果是多行文本,可以设置PCRE_DOTALL的选项pcre_complie(re, PCRE_DOTALL,....),表示'.'也匹配回车换行"\r\n"。