@[TOC](C语言正则表达式库 pcre2 简述(chitGPT给出的回答和我的补充))
PCRE2(Perl Compatible Regular Expression 2)是一个支持 Perl 语法的正则表达式库。它是 PCRE(Perl Compatible Regular Expression)的升级版,提供了更多的功能和更高的性能。
PCRE2 可以用于 C、C++、Java、Python、PHP 等多种编程语言中,用于处理文本匹配、搜索和替换等操作。
使用 PCRE2,需要先安装库文件和头文件。然后在代码中包含头文件,调用相应的函数进行正则表达式的操作。例如,以下是一个 C++ 中使用 PCRE2 进行正则表达式匹配的示例:
#include <iostream>
#include <pcre2.h>
int main()
{
// 定义正则表达式
PCRE2_SPTR pattern = (PCRE2_SPTR) "hello (world)";
// 定义输入字符串
PCRE2_SPTR input = (PCRE2_SPTR) "hello world, hello PCRE2!";
// 编译正则表达式
pcre2_code *re;
int errorcode;
PCRE2_SIZE erroroffset;
re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &errorcode,
&erroroffset, NULL);
// 匹配正则表达式
pcre2_match_data *match_data;
match_data = pcre2_match_data_create_from_pattern(re, NULL);
int rc;
rc = pcre2_match(re, input, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL);
// 输出匹配结果
if (rc > 0)
{
PCRE2_SPTR substring_start;
PCRE2_SIZE substring_length;
substring_start =
pcre2_get_substring(input, match_data, 1, &substring_length);
std::cout << "Match: ";
std::cout.write((char *)substring_start, substring_length);
std::cout << std::endl;
pcre2_substring_free(substring_start);
}
// 释放内存
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
以上代码定义了一个正则表达式 hello (world),表示匹配字符串中的 hello world。然后编译正则表达式,使用 pcre2_match 函数进行匹配,如果成功则输出匹配结果。
PCRE2 还提供了许多其他的函数和选项,可以根据需要进行使用。
要在 PCRE2 中匹配中文,您需要考虑以下几点:
中文的编码方式:中文通常使用 UTF-8 编码,所以您需要确保在 PCRE2 中使用 UTF-8 编码。
使用 Unicode 属性:PCRE2 提供了 Unicode 属性,可以识别不同的字符类别,包括中文字符。
以下是一个使用 PCRE2 匹配中文的示例代码:
#include <pcre2.h>
#include <stdio.h>
int main()
{
const char *pattern = "\\p{Han}+"; // 匹配中文字符
const char *subject = "你好,世界!Hello, world!";
PCRE2_SPTR pattern_utf8 = (PCRE2_SPTR)pattern;
PCRE2_SPTR subject_utf8 = (PCRE2_SPTR)subject;
int errorcode, rc;
PCRE2_SIZE erroroffset;
pcre2_code *re;
pcre2_match_data *match_data;
// 编译正则表达式
re = pcre2_compile(pattern_utf8, PCRE2_ZERO_TERMINATED, 0, &errorcode,
&erroroffset, NULL);
if (re == NULL)
{
printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,
pcre2_get_error_message(errorcode));
return 1;
}
// 准备匹配数据
match_data = pcre2_match_data_create_from_pattern(re, NULL);
// 执行匹配
rc = pcre2_match(re, subject_utf8, PCRE2_ZERO_TERMINATED, 0, 0, match_data,
NULL);
if (rc < 0)
{
printf("PCRE2 matching failed: %d\n", rc);
return 1;
}
// 输出匹配结果
printf("Matched %d characters:\n", rc);
PCRE2_SPTR match_str = subject_utf8 + pcre2_get_startchar(match_data);
for (int i = 0; i < rc; i++)
{
printf("%c", (char)match_str[i]);
}
printf("\n");
// 释放资源
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
该示例使用 \p{Han}+ 正则表达式匹配中文字符,输出结果为:
Matched 6 characters:
你好世界
注意,由于中英文字符混合,输出结果可能不是您期望的。如果您只想匹配中文字符,可以将正则表达式修改为 \p{Han}+。
上面是CSDN的AI模型chitGPT做的有关pcre2正常表达式库的简要介绍, 我先验证一下, 看看代码有没有什么问题.
很遗憾, 上面两个代码都有相当错误, 需要修改, 修改后的代码见下面
编译参数:需要引入8位和16位的库(不冲突)
E:\msys64\clang64\bin\clang.exe -glldb -lpcre2-16 -lpcre2-8 test196_8*.c -o E:\clangC++\answer\C\test196_8.exe
第一个程序:
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#include <stdio.h>
int main()
{
// 定义正则表达式
PCRE2_SPTR pattern = (PCRE2_SPTR) "hell(\\w)"; // (world)";
// 定义输入字符串
PCRE2_SPTR input = (PCRE2_SPTR) "hellp hello world, PCRE2!";
// 编译正则表达式
pcre2_code *re;
int errorcode;
PCRE2_SIZE erroroffset;
re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &errorcode,
&erroroffset, NULL);
// 匹配正则表达式
pcre2_match_data *match_data =
pcre2_match_data_create_from_pattern(re, NULL);
int rc =
pcre2_match(re, input, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL);
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
// 输出匹配结果
while (rc > 0)
{
printf("Match: \n");
PCRE2_SPTR substring_start;
PCRE2_SIZE substring_length;
for (int i = 0; i < rc; i++)
{
substring_start = input + ovector[2 * i];
substring_length = ovector[2 * i + 1] - ovector[2 * i];
printf("%2d: %.*s\n", i, (int)substring_length,
(char *)substring_start);
}
input = substring_start + substring_length;
rc = pcre2_match(re, input, PCRE2_ZERO_TERMINATED, 0, 0, match_data,
NULL);
ovector = pcre2_get_ovector_pointer(match_data);
}
// 释放内存
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
第二个程序:
#define PCRE2_CODE_UNIT_WIDTH 16
#include <locale.h>
#include <pcre2.h>
#include <stdio.h>
int main()
{
setlocale(LC_CTYPE, "");
PCRE2_SPTR16 pattern_utf16 =
(PCRE2_SPTR16)L"(\\p{Han})+"; // 匹配中文字符pattern;
PCRE2_SPTR16 subject_utf16 =
(PCRE2_SPTR16)L"Hello, world! 你好,世界!"; // subject;
int errorcode;
int rc;
size_t erroroffset;
pcre2_code_16 *re;
pcre2_match_data_16 *match_data;
// 编译正则表达式
re = pcre2_compile_16(pattern_utf16, PCRE2_ZERO_TERMINATED, 0, &errorcode,
&erroroffset, NULL);
if (re == NULL)
{
PCRE2_UCHAR16 buffer[256];
pcre2_get_error_message_16(errorcode, buffer, sizeof(buffer));
wprintf(L"PCRE2 compilation failed at offset %d: %s\n",
(int)erroroffset, buffer);
return 1;
}
// 准备匹配数据
match_data = pcre2_match_data_create_from_pattern_16(re, NULL);
// 执行匹配
rc = pcre2_match_16(re, subject_utf16, PCRE2_ZERO_TERMINATED, 0, 0,
match_data, NULL);
if (rc < 0)
{
printf("PCRE2 matching failed: %d\n", rc);
return 1;
}
// 输出匹配结果
printf("Matched %d characters:\n", rc);
PCRE2_SPTR16 match_str = subject_utf16 + pcre2_get_startchar_16(match_data);
for (int i = 0; i < rc; i++)
{
wprintf(L"%c", (wchar_t)match_str[i]);
}
printf("\n");
// 释放资源
pcre2_match_data_free_16(match_data);
pcre2_code_free_16(re);
return 0;
}
貌似AI对于这个正则库的api并不熟悉, 而且还会自造函数, 这确实令人苦恼, 关键是我想通过AI快速掌握这个库, 结果还是需要看文档.
以下是文档中核心函数的最简要解说.
此正则库有三种编码, 8,16,32位, 对于普通ASCII码, 8位即可, 中文需要16位(Windows环境)
#define PCRE2_CODE_UNIT_WIDTH 16
为了用中文, 需要给出区域头文件, 加上库文件
#include <locale.h>
#include <pcre2.h>
设置中文环境
const char *loc = setlocale(LC_CTYPE, "");
用宽字符声明模式字符串
PCRE2_SPTR16 pattern = (PCRE2_SPTR16)L"\\p{Han}+"; // 匹配中文字符pattern;
声明匹配字符串
PCRE2_SPTR16 subject =
(PCRE2_SPTR16)L"Hello, world! 你好,世界!"; // subject;
编译正则表达式
int errorcode;
size_t erroroffset;
// 编译正则表达式
pcre2_code_16 *re = pcre2_compile_16(
pattern, // 模式字符串
PCRE2_ZERO_TERMINATED, // 字符长度
0, // 默认选项
&errornumber, // 错误号
&erroroffset, // 错误偏移
NULL); // 一般用NULL
如果编译返回NULL, 输出错误结束程序
if (re == NULL)
{
PCRE2_UCHAR16 buffer[256];
pcre2_get_error_message_16(errorcode, buffer, sizeof(buffer));
wprintf(L"PCRE2 compilation failed at offset %d: %s\n",
(int)erroroffset, buffer);
return 1;
}
声明一个匹配数据, 用于存放匹配结果
// 准备匹配数据
pcre2_match_data_16 *match_data =
pcre2_match_data_create_from_pattern_16(re, NULL);
执行匹配
size_t offset = 0;
// 匹配成功的数量
int rc = pcre2_match_16(re, // 正则表达式
subject, // 待匹配字符串
PCRE2_ZERO_TERMINATED, // 字符串长度
offset, // 开始匹配时的偏移量
0, // 默认选项
match_data, // 匹配数据存放地址
NULL // 默认为NULL
);
if (rc < 0)
{
printf("PCRE2 matching failed: %d\n", rc);
return 1;
}
获取匹配数组, 匹配位置偏移量存储在此数组中
size_t *ovector = pcre2_get_ovector_pointer_16(match_data);
输出匹配结果
while (rc > 0)
{
printf("Match: \n");
for (int i = 0; i < rc; i++)
{
wprintf(L"%2d: %.*s\n", i,
(int)(ovector[2 * i + 1] - ovector[2 * i]), // 匹配的开始和结束位置在ovector数组中, 求差得出匹配字符个数
(wchar_t *)(subject + ovector[2 * i])); // 通过偏移到达匹配位置, 从匹配的第一个字符开始打印
}
offset = ovector[2 * (rc - 1) + 1]; // 设置本次匹配字符结尾的偏移量, 做下一次匹配的开始位置
rc = pcre2_match_16(re, subject, PCRE2_ZERO_TERMINATED,
offset, // 从上次匹配的末尾开始匹配
0,
match_data, NULL);
ovector = pcre2_get_ovector_pointer_16(match_data); // 获取匹配结果数组
}
将正则表达式和匹配数据资源回收
// 释放资源
pcre2_match_data_free_16(match_data);
pcre2_code_free_16(re);
以上就是正则库的简述, 目前还是自己看文档, AI还暂时不能解决这种问题.