如何在C语言中使用pcre2_substitute实现全部匹配项替换?
如何用pcre2_substitute实现全局替换?
我现在用pcre2_substitute只能替换首个匹配项,代码如下:
#define PCRE2_CODE_UNIT_WIDTH 8 #include <stdio.h> #include <string.h> #include <pcre2.h> int main(int argc, char **argv) { PCRE2_SPTR pattern = "(\\d+)"; PCRE2_SPTR subject = "1 something 849 for 993"; PCRE2_SPTR replacement = "XXX"; pcre2_code *re; int errornumber; int i; int rc; PCRE2_SIZE erroroffset; PCRE2_SIZE *ovector; size_t subject_length; size_t replacement_length = strlen((char *)replacement); pcre2_match_data *match_data; subject_length = strlen((char *)subject); PCRE2_UCHAR output[1024] = ""; PCRE2_SIZE outlen = sizeof(output) / sizeof(PCRE2_UCHAR); re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL); if (re == NULL) { PCRE2_UCHAR buffer[256]; pcre2_get_error_message(errornumber, buffer, sizeof(buffer)); printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset, buffer); } match_data = pcre2_match_data_create_from_pattern(re, NULL); rc = pcre2_substitute(re, subject, subject_length, 0, 0, match_data, NULL, replacement, replacement_length, output, &outlen); printf("Output: %s", output); return 0; }
我知道要循环调用pcre2_substitute来替换后续匹配项,但不确定怎么安全地把output作为下一次调用的subject参数传入。
实现全局替换的两种方式
方式一:使用PCRE2_SUBSTITUTE_GLOBAL标志(推荐)
不需要手动循环,直接给pcre2_substitute传入PCRE2_SUBSTITUTE_GLOBAL标志,就能一次性替换所有匹配项:
修改后的核心调用代码:
rc = pcre2_substitute( re, subject, subject_length, 0, PCRE2_SUBSTITUTE_GLOBAL, // 开启全局替换 match_data, NULL, replacement, replacement_length, output, &outlen );
这种方式简洁高效,是官方推荐的全局替换方案。
方式二:手动循环(适合需要自定义替换逻辑的场景)
如果必须手动循环,关键是用双缓冲区交替存储输入和输出,避免替换时覆盖未处理的输入数据。以下是完整示例:
#define PCRE2_CODE_UNIT_WIDTH 8 #include <stdio.h> #include <string.h> #include <pcre2.h> #include <stdlib.h> int main(int argc, char **argv) { PCRE2_SPTR pattern = "(\\d+)"; PCRE2_SPTR initial_subject = "1 something 849 for 993"; PCRE2_SPTR replacement = "XXX"; pcre2_code *re; int errornumber; int rc; PCRE2_SIZE erroroffset; pcre2_match_data *match_data; size_t replacement_length = strlen((char *)replacement); // 双缓冲区交替使用,防止输入被覆盖 PCRE2_UCHAR buf1[1024], buf2[1024]; PCRE2_SPTR current_subject = initial_subject; size_t current_length = strlen((char *)current_subject); PCRE2_UCHAR *output_buf = buf1; PCRE2_SIZE outlen; // 编译正则表达式 re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL); if (re == NULL) { PCRE2_UCHAR buffer[256]; pcre2_get_error_message(errornumber, buffer, sizeof(buffer)); printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset, buffer); return 1; } match_data = pcre2_match_data_create_from_pattern(re, NULL); do { // 重置输出缓冲区 outlen = sizeof(buf1) / sizeof(PCRE2_UCHAR); memset(output_buf, 0, outlen); // 单次替换首个匹配项 rc = pcre2_substitute( re, current_subject, current_length, 0, 0, match_data, NULL, replacement, replacement_length, output_buf, &outlen ); if (rc < 0) { if (rc == PCRE2_ERROR_NOMATCH) { // 无更多匹配,输出结果 printf("Output: %s\n", current_subject == initial_subject ? initial_subject : (current_subject == buf1 ? buf2 : buf1)); break; } else { // 处理其他错误 PCRE2_UCHAR buffer[256]; pcre2_get_error_message(rc, buffer, sizeof(buffer)); printf("Substitute error: %s\n", buffer); break; } } // 交换输入输出缓冲区 if (current_subject == initial_subject) { current_subject = output_buf; } else { current_subject = (output_buf == buf1) ? buf2 : buf1; } current_length = outlen; output_buf = (output_buf == buf1) ? buf2 : buf1; } while (1); // 释放资源 pcre2_match_data_free(match_data); pcre2_code_free(re); return 0; }
关键注意点
- 双缓冲区交替:每次替换用一个缓冲区存输入,另一个存输出,避免数据覆盖。
- 循环终止:当
pcre2_substitute返回PCRE2_ERROR_NOMATCH时,说明没有更多匹配项,终止循环。 - 资源释放:必须释放编译后的正则表达式和匹配数据,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Googlebot
相关产品推荐
相关产品推荐

