c 正则表达式 regex.h匹配提取示例
时间:2026-08-10 | 作者:白桃企划师 | 阅读:0本文聚焦Linux、macOS及其他类Unix系统提供的POSIX regex.h接口,介绍如何在C语言程序中完成正则模式编译、字符串匹配、捕获内容提取、错误诊断和资源释放,并说明Windows开发时可采用的PCRE2方案。
C语言中的POSIX正则表达式支持
ISO C标准库没有内置正则表达式模块。Linux、macOS及其他类Unix系统通常提供POSIX正则接口,使用时需要包含regex.h。其基本工作过程是先调用regcomp编译模式,再通过regexec匹配字符串,最后调用regfree释放编译结果。本文代码适用于提供POSIX regex.h的系统。Windows通常不原生提供这套接口:如果项目必须沿用regex.h,可选用经过维护的POSIX兼容环境或兼容库;如果需要原生跨平台方案,通常选择PCRE2,安装PCRE2开发库后包含pcre2.h,并依次使用pcre2_compile、pcre2_match、pcre2_get_ovector_pointer和pcre2_code_free。PCRE2的API和正则语法均不能与regex.h代码直接互换。
编译正则模式
regcomp用于把模式字符串编译到regex_t对象中。常用标志REG_EXTENDED表示采用扩展正则语法,可直接使用加号、问号和分组等结构;REG_ICASE表示忽略英文字母大小写;REG_NOSUB表示只判断是否匹配,不保存匹配位置。函数返回零表示编译成功,非零返回值应交给regerror转换为可读错误信息。只有编译成功后,才能把该对象传给regexec,也只有成功编译的对象才应调用regfree释放。
regex_t regex;int result = regcomp(®ex, "^[0-9]+$", REG_EXTENDED);- result不为零时,使用regerror读取错误原因
执行匹配并提取内容
regexec负责在目标字符串中执行已经编译的模式。返回零代表匹配成功,返回REG_NOMATCH代表没有匹配,其余返回值表示执行错误,并可同样传给regerror生成可读诊断。如果需要提取完整匹配或捕获组,可以准备regmatch_t数组。matches[0]表示完整匹配,后续元素依次对应捕获组;rm_so是起始字节偏移,rm_eo是结束字节偏移。未参与匹配的可选分组通常以rm_so和rm_eo为-1表示,复制前必须检查。提取时按rm_eo-rm_so计算字节数,使用memcpy复制并在末尾添加字符串结束符。偏移量按字节计算,因此处理中文等多字节文本时,不能直接把它当作字符数量。
- regmatch_t matches[2]可保存完整匹配和一个捕获分组
if (matches[1].rm_so != -1) { size_t len = (size_t)(matches[1].rm_eo - matches[1].rm_so); char group[64]; if (len < sizeof group) { memcpy(group, text + matches[1].rm_so, len); group[len] = ' '; } }- 目标缓冲区至少需要匹配字节数加1字节;长度超出缓冲区时应拒绝复制或改为动态分配
完整可编译示例
下面的程序使用捕获组从字符串中提取数字,并完整区分编译失败、未匹配和执行失败。regcomp失败时,regex对象尚未成功编译,因此程序直接报告错误而不调用regfree;编译成功后,无论regexec结果如何,退出前都会调用regfree。Linux和macOS通常可直接使用系统提供的POSIX接口编译,无需额外链接正则库。
代码:
#include#include #include #include int main(void) { const char *pattern = "^ID:([0-9]+)$"; const char *text = "ID:2026"; regex_t regex; regmatch_t matches[2]; int rc = regcomp(®ex, pattern, REG_EXTENDED); if (rc != 0) { size_t size = regerror(rc, ®ex, NULL, 0); char *message = malloc(size); if (message != NULL) { regerror(rc, ®ex, message, size); fprintf(stderr, "正则编译失败: %sn", message); free(message); } else { fprintf(stderr, "正则编译失败,且无法分配错误缓冲区n"); } return 1; } rc = regexec(®ex, text, 2, matches, 0); if (rc == 0) { if (matches[1].rm_so == -1) { fprintf(stderr, "捕获组未参与匹配n"); regfree(®ex); return 1; } size_t length = (size_t)(matches[1].rm_eo - matches[1].rm_so); char *value = malloc(length + 1); if (value == NULL) { fprintf(stderr, "无法分配提取缓冲区n"); regfree(®ex); return 1; } memcpy(value, text + matches[1].rm_so, length); value[length] = ' '; printf("完整匹配: %.*sn", (int)(matches[0].rm_eo - matches[0].rm_so), text + matches[0].rm_so); printf("提取的数字: %sn", value); free(value); } else if (rc == REG_NOMATCH) { printf("字符串不匹配n"); } else { size_t size = regerror(rc, ®ex, NULL, 0); char *message = malloc(size); if (message != NULL) { regerror(rc, ®ex, message, size); fprintf(stderr, "正则执行失败: %sn", message); free(message); } else { fprintf(stderr, "正则执行失败,且无法分配错误缓冲区n"); } regfree(®ex); return 1; } regfree(®ex); return 0; } - Linux/macOS编译命令:
cc -std=c11 -Wall -Wextra -pedantic regex_demo.c -o regex_demo - 运行命令:
./regex_demo
常见问题与改进建议
C字符串中的反斜杠本身具有转义含义,所以正则模式需要反斜杠时,通常要在字符串字面量中写成两个反斜杠。POSIX扩展正则与PCRE2语法并不完全相同,不应直接照搬所有网络示例。频繁处理相同模式时,可以只编译一次并重复调用regexec,以减少开销;多线程共享编译对象前,则应结合具体实现文档确认使用方式。处理不可信文本时还要关注输入规模,避免复杂模式造成过高的匹配成本。Windows原生项目若选择PCRE2,需要按PCRE2文档安装并链接8位、16位或32位库中的一种;处理普通char字符串时通常选择8位库,并在包含pcre2.h前定义PCRE2_CODE_UNIT_WIDTH 8。
掌握编译、匹配、内容提取、错误诊断和资源释放后,就能在提供POSIX regex.h的系统中稳定使用正则表达式。Linux、macOS等类Unix平台可采用本文示例;Windows原生或需要统一跨平台语法的项目,应优先评估PCRE2,并按其独立API改写编译、匹配、提取和释放流程。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- c 语言基础教程怎么入门?语法、流程与示例说明
- 时间:2026-08-13
-
- c实现多线程 pthread创建回收与互斥锁同步
- 时间:2026-08-10
-
- c++11 正则表达式 std::regex写法与异常处理
- 时间:2026-08-10
-
- 多线程c语言实现 pthread创建同步与完整示例
- 时间:2026-08-10
-
- vc 正则表达式 std::regex与Boost.Regex选择
- 时间:2026-08-10
-
- c++ 正则表达 regex匹配提取替换示例
- 时间:2026-08-10
-
- c的多线程怎么实现原理 pthread原理与加锁示例
- 时间:2026-08-10
-
- 正则表达式c语言
- 时间:2026-08-10
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15