C++中PCRE2多段匹配实现问题:为何返回PCRE2_ERROR_NOMATCH?
问题分析与解决
核心错误原因
你对PCRE2多段匹配的逻辑理解有误:
- 文档中说的“将下一段追加到第一段后”,是指把后续数据拼接到第一段的末尾,形成完整的待匹配数据流,然后在这个完整数据流上从第一次部分匹配的结束偏移位置开始匹配。
- 但你的代码中直接拿
string_two(内容是"one hundred")作为匹配目标,并从偏移量4的位置开始匹配——此时string_two的第4位开始是"undred",和正则表达式"one hundred"需要的后续内容("hundred"前需接空格)完全不匹配,所以返回PCRE2_ERROR_NOMATCH。
修正方案
需要先将两段数据拼接成完整的数据流,再在这个完整流上执行后续匹配。以下是修正后的代码:
// #define PCRE2_CODE_UNIT_WIDTH 0 // #include <pcre2.h> #include <cstdio> #include <cstdlib> #include <string> // Variable initialisation char const *string_one = "one "; char const *string_two = "one hundred"; int error_number; PCRE2_SIZE error_offset; int return_code; // 拼接两段数据成完整字符串 std::string full_string = string_one; full_string += string_two; auto *code = pcre2_compile_8((PCRE2_SPTR8) "one hundred", PCRE2_ZERO_TERMINATED, 0, &error_number, &error_offset, NULL); if (code == NULL) { fprintf(stderr, "`pcre2_compile` failed\n"); exit(1); } auto *match_data = pcre2_match_data_create_from_pattern_8(code, NULL); auto *ovector = pcre2_get_ovector_pointer_8(match_data); // 第一次匹配:处理第一段数据 return_code = pcre2_match_8(code, (PCRE2_SPTR8) string_one, PCRE2_ZERO_TERMINATED, 0, PCRE2_PARTIAL_HARD, match_data, NULL); if (return_code == PCRE2_ERROR_PARTIAL) { PCRE2_SIZE offset = ovector[1]; // 第二次匹配:在完整拼接的字符串上从偏移位置开始匹配 return_code = pcre2_match_8(code, (PCRE2_SPTR8) full_string.c_str(), full_string.length(), // 明确传入长度,避免零终止问题 offset, PCRE2_PARTIAL_HARD | PCRE2_NOTBOL, match_data, NULL); printf("[rc]: %d\n", return_code); // 此时会返回0,表示匹配成功 } // 释放PCRE2资源 pcre2_match_data_free_8(match_data); pcre2_code_free_8(code);
关键改动说明
- 拼接数据流:将
string_one和string_two拼接成完整的full_string,模拟真实场景中分段接收的完整数据。 - 明确传入字符串长度:第二次匹配时使用
full_string.length()替代PCRE2_ZERO_TERMINATED,避免拼接后可能出现的零终止符问题(本例中虽无此问题,但这是更严谨的写法)。 - 资源释放:补充了PCRE2资源的释放代码,避免内存泄漏。
额外说明
如果是处理超大数据流(无法一次性拼接),可以使用PCRE2的部分匹配上下文(通过pcre2_match_context_create创建上下文,结合PCRE2_PARTIAL_SOFT或PCRE2_PARTIAL_HARD跟踪匹配状态),但对于小数据场景,直接拼接是最简单可靠的方式。
内容的提问来源于stack exchange,提问作者D. Ataro
相关产品推荐
相关产品推荐

