C: GNU regex library (regex.h)正则表达式调用示例
Posted 10km
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C: GNU regex library (regex.h)正则表达式调用示例相关的知识,希望对你有一定的参考价值。
GNU regex是GNU提供的跨平台的POSIX 正则表达式库(C语言)。
我也是最近才接触这个相对于C++/Java实现来说非常简陋,勉强够用的正则表达式库。
不算GNU提供的扩展函数,POSIX标准的regex库总共就4个函数regcomp
,regerror
,regexec
,regfree
,
以下以完整源码的方式调用以上函数完成对GNU regex library的基本测试。
gnuregex_test.c
详细解释参见源码中的注释
/************************************************************************/
/* gnuregex_test.c */
/* GNU Regex 测试 */
/* 测试 regcomp,regerror,regexec,regfree 函数的使用方式 */
/* author guyadong */
/************************************************************************/
#include <stdio.h>
#include <regex.h>
/** 输出字符串中指定范围的字符到控制台 */
void print_str(const char* input, size_t _start, size_t _end)
if (input)
for (size_t i = _start; i < _end; ++i)
printf("%c", input[i]);
int main()
/** 待匹配字符串 */
const char* inputstr = "hello,welcome to my party";
/** regex 错误输出缓冲区 */
char regerrbuf[256];
regex_t reg;
/** 正则表达式 */
const char* pattern = "(we|par)([a-z]+)";
printf("==GNU Regex Test==\\n");
printf("Pattern :%s\\n", pattern);
printf("Input String:%s\\n", inputstr);
/************************************************************************/
/* 编译正则表达式,编译成功的 regex_t 对象才可以被后续的 regexec 使用 */
/************************************************************************/
int c = regcomp(®, pattern, REG_EXTENDED);
if (0 != c)
/************************************************************************/
/* 正则表达式编译出错输出错误信息 */
/* 调用 regerror 将错误信息输出到 regerrbuf 中 */
/* regerrbuf 末尾置0,确保上面调用regerror 导致 regerrbuf 溢出的情况下, */
/* 字符串仍有有结尾0 */
/* 然后 printf 输出 */
/************************************************************************/
regerror(c, ®, regerrbuf, sizeof(regerrbuf));
regerrbuf[sizeof(regerrbuf) - 1] = '\\0';
printf("%s\\n", regerrbuf);
return -1;
/************************************************************************/
/* 记录匹配位置的 regmatch_t 数组 */
/* 上面的正则表达有 2 个捕获组,加上默认组(group 0), */
/* 为了记录所有捕获组位置,所以这里需要长度为 3 的 regmatch_t 数组 */
/************************************************************************/
const size_t matchsz = 3;
regmatch_t pmatch[3];
/** 起始匹配的偏移量 */
size_t offset = 0;
/** 捕获计数 */
int matchcount = 0;
/************************************************************************/
/* regexec 不能通过一次调用找到字符串中所有满足匹配条件的字符串位置, */
/* 所以需要通过步进偏移的方式循环查找字符串中所有匹配的字符串, */
/* 每一次匹配的起始偏移是上一次匹配到的字符串结束偏移 */
/************************************************************************/
do
printf("Search start %d\\n",(int)offset);
/** 正则表达式匹配的起始地址 */
const char* p = inputstr + offset;
/************************************************************************/
/* regmatch_t 用于记录正则表达匹配的结果,每一个 regmatch_t 记录一个捕获 */
/* 组(catch group)的在字符串中的起始位置。 */
/* 如果调用 regexec 时如果不提供 regmatch_t(nmatch为0,pmatch为NULL), */
/* 或者提供的 regmatch_t 数组长小于正则表达式中全部捕获组的数量, */
/* regexec 也能正常匹配,只是无法记录匹配的位置 */
/* 或不能完全记录所有的匹配结果 */
/************************************************************************/
c = regexec(®, p, matchsz, pmatch, 0);
if (REG_NOMATCH == c)
/** 没有找到匹配结束循环 */
printf("MATCH FINISHED\\n");
break;
else if (0 == c)
/** 找到匹配,则输出匹配到的所有捕获组(catch group) */
printf("%d MATCH (%d-%d)\\n", ++matchcount, pmatch[0].rm_so, pmatch[0].rm_eo);
for (int i = 0; i < matchsz; ++i)
printf("group %d :<<", i);
print_str(p, pmatch[i].rm_so, pmatch[i].rm_eo);
printf(">>\\n");
/************************************************************************/
/* 使用整体匹配捕获组0(group 0)的结束位置的更新偏移量, */
/* 下一次匹配从当前匹配的结束位置开始 */
/************************************************************************/
offset += pmatch[0].rm_eo;
continue;
else
/************************************************************************/
/** regexec 调用出错输出错误信息,结束循环 */
/************************************************************************/
regerror(c, ®, regerrbuf, sizeof(regerrbuf));
regerrbuf[sizeof(regerrbuf) - 1] = '\\0';
printf("%s\\n", regerrbuf);
break;
while (1);
printf("%d MATCH FOUND\\n", matchcount);
/************************************************************************/
/** regfree 必须与 regcomp 配对使用,否则会发生内存泄露 */
/************************************************************************/
regfree(®);
return 0;
运行输出:
>gnuregex_test.exe
==GNU Regex Test==
Pattern :(we|par)([a-z]+)
Input String:hello,welcome to my party
Search start 0
1 MATCH (6-13)
group 0 :<<welcome>>
group 1 :<<we>>
group 2 :<<lcome>>
Search start 13
2 MATCH (7-12)
group 0 :<<party>>
group 1 :<<par>>
group 2 :<<ty>>
Search start 25
MATCH FINISHED
2 MATCH FOUND
说明
- 调用
regcomp
时对regex_t
对象会有分配内存,所以用完的regex_t
对象一定要调用regfree
释放,否则会发生内存泄露。 - 如果只是想判断字符串是否匹配正则表达式,而不关心匹配的位置,在执行
regexec
可以不需要填保存匹配结果的regmatch_t
相关参数,即第3,4个参数(__nmatch
,__pmatch
)填0. - 如果字符串有多个匹配,
regexec
不能通过一次调用找到字符串中所有满足匹配条件的字符串位置,所以需要通过步进偏移的方式循环查找字符串中所有匹配的字符串,每一次匹配的起始偏移是上一次匹配到的字符串结束偏移
libgnurx-msvc
以上代码在MSVC和gcc编译运行通过。
因为MSVC没有提供GNU regex库,在windows下编译上面的代码所需要的GNU regex library请参见我另一篇博客
《MSVC下使用gnu regex(正则表达式C语言接口regex.h)》
上面的完整的可编译代码以及GNU regex library for MSVC,我放在了码云仓库:
https://gitee.com/l0km/libgnurx-msvc.git
以上是关于C: GNU regex library (regex.h)正则表达式调用示例的主要内容,如果未能解决你的问题,请参考以下文章
MSVC下使用gnu regex(正则表达式C语言接口regex.h)
C:基于GNU regex(regex.h)regexec实现正则表达式多次匹配