如何在C语言中使用pcre2.h库分割字符串(采用GPT-2分词器正则表达式)
如何在C语言中使用pcre2.h库分割字符串(采用GPT-2分词器正则表达式)
嘿,我来帮你搞定用PCRE2结合GPT-2分词正则分割字符串的事儿!你的代码已经有了开头,我来帮你补全并解释每一步该怎么做。
首先,先明确GPT-2的分词正则完整模式,你之前写的pattern没写完,完整的应该是(注意C字符串里的转义字符要多加一个反斜杠):
const char* pattern = "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+";
接下来是完整的可运行代码,我会在代码里加上注释,之后再逐点解释:
#define PCRE2_CODE_UNIT_WIDTH 8 #define PCRE2_STATIC #include "pcre2.h" #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { pcre2_code* re; PCRE2_SIZE erroffset; int errcode; PCRE2_UCHAR8 error_buffer[128]; // GPT-2分词完整正则表达式 const char* pattern = "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+"; PCRE2_UCHAR8* subject = (PCRE2_UCHAR8*)"Hello, world! I'm using GPT-2 tokenizer in C with PCRE2."; // 编译正则表达式 re = pcre2_compile( (PCRE2_UCHAR8*)pattern, PCRE2_ZERO_TERMINATED, 0, // 选项:默认即可,无需特殊设置 &errcode, &erroffset, NULL); // 编译上下文:用默认的NULL即可 if (re == NULL) { // 编译失败时打印错误信息 pcre2_get_error_message(errcode, error_buffer, sizeof(error_buffer)); printf("正则编译失败,错误位置:%zu,错误信息:%s\n", erroffset, error_buffer); return 1; } // 创建匹配上下文 pcre2_match_context* match_ctx = pcre2_match_context_create(NULL); if (match_ctx == NULL) { printf("创建匹配上下文失败\n"); pcre2_code_free(re); return 1; } // 分配ovector:每个匹配需要2个元素存起止位置,PCRE2要求至少3个元素 PCRE2_SIZE ovector[3]; PCRE2_SIZE subject_length = pcre2_get_string_length(subject); PCRE2_SIZE start_offset = 0; int rc; printf("分词结果:\n"); // 循环匹配,直到遍历完整个字符串 while ((rc = pcre2_match( re, subject, subject_length, start_offset, 0, // 匹配选项:默认 ovector, sizeof(ovector)/sizeof(ovector[0]), match_ctx)) >= 0) { // 提取当前匹配的token起止位置 PCRE2_SIZE start = ovector[0]; PCRE2_SIZE end = ovector[1]; PCRE2_SIZE token_length = end - start; // 打印当前token printf("- "); fwrite(subject + start, 1, token_length, stdout); printf("\n"); // 移动起始位置到当前匹配的末尾,继续下一次匹配 start_offset = end; // 到达字符串末尾就退出循环 if (start_offset >= subject_length) { break; } } // 处理匹配结束的情况 if (rc == PCRE2_ERROR_NOMATCH) { printf("已完成所有分词\n"); } else { pcre2_get_error_message(rc, error_buffer, sizeof(error_buffer)); printf("匹配出错:%s\n", error_buffer); } // 释放所有资源,避免内存泄漏 pcre2_match_context_free(match_ctx); pcre2_code_free(re); return 0; }
关键步骤说明
- 正则编译:
pcre2_compile把正则字符串转换成PCRE2可处理的二进制结构,编译失败一定要检查错误信息,大概率是正则语法写错了。 - 匹配上下文:用来设置匹配的额外参数,这里用默认配置就行,不用额外调整。
- ovector数组:存储每个匹配的起始和结束偏移量,PCRE2要求数组长度至少是3,即使你不需要捕获分组。
- 循环匹配:每次匹配成功后提取token,然后把起始位置移到当前匹配的末尾,直到遍历完整个字符串。
- 资源释放:PCRE2的动态资源要手动释放,比如编译后的正则代码、匹配上下文,不然会有内存泄漏。
编译注意事项
编译的时候要链接PCRE2库,比如用gcc的话,命令是:
gcc your_code.c -o tokenizer -lpcre2-8
-lpcre2-8对应我们设置的PCRE2_CODE_UNIT_WIDTH 8,也就是UTF-8编码,能正常处理中文等Unicode字符。
内容来源于stack exchange
相关产品推荐
相关产品推荐

