在c++项目中使用pcre2

Using pcre2 in a c++ project

本文关键字:pcre2 c++ 项目      更新时间:2023-10-16

我正在考虑在我的简单c++应用程序中使用pcre2(我使用的是vs2015(。(我正在查看各种regex库,总体感觉是pcre/pcre2是最灵活的(

首先,我从官方位置下载了pcre2(http://sourceforge.net/projects/pcre/files/pcre2/10.20/)并创建了一个非常简单的示例。

#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
...
PCRE2_SPTR subject = (PCRE2_SPTR)std::string("this is it").c_str();
PCRE2_SPTR pattern = (PCRE2_SPTR)std::string("([a-z]+)|\s").c_str();
...
int errorcode;
PCRE2_SIZE erroroffset;
pcre2_code *re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 
                                PCRE2_ANCHORED | PCRE2_UTF, &errorcode,  
                                &erroroffset, NULL);
...

首先,文件">pcre2.h"不存在,所以我将pcre2.h.generic重命名为pc re2.h

但后来我得到了链接器错误与未解析的外部。

我想我需要包含一个或多个从源到项目的文件。但我不愿意在不知道它的作用的情况下随意添加文件。

有人能给出一些简单的步骤来成功地使用pcre2构建项目吗?

更新
这不是导入库的问题,pcre2.h没有库(我在它们的发布位置看不到(。

如果你不介意使用包装器,这里是我的:JPCRE2

您需要根据要使用的字符串类(分别为std::stringstd::wstringstd::u16stringstd::u32string(选择基本字符类型(charwchar_tchar16_tchar32_t(:

typedef jpcre2::select<char> jp;
//Selecting char as the basic character type will require
//8 bit PCRE2 library where char is 8 bit,
//or 16 bit PCRE2 library where char is 16 bit,
//or 32 bit PCRE2 library where char is 32 bit.
//If char is not 8, 16 or 32 bit, it's a compile error.

匹配示例:

检查字符串是否与模式匹配:

if(jp::Regex("(\d)|(\w)").match("I am the subject")) 
    std::cout<<"nmatched";
else
    std::cout<<"nno match";

全部匹配并获取匹配计数:

size_t count = 
jp::Regex("(\d)|(\w)","mi").match("I am the subject", "g");
// 'm' modifier enables multi-line mode for the regex
// 'i' modifier makes the regex case insensitive
// 'g' modifier enables global matching

获取编号的子字符串/捕获的组:

jp::VecNum vec_num;
count = 
jp::Regex("(\w+)\s*(\d+)","im").initMatch()
                                  .setSubject("I am 23, I am digits 10")
                                  .setModifier("g")
                                  .setNumberedSubstringVector(&vec_num)
                                  .match();
std::cout<<"nTotal match of first match: "<<vec_num[0][0];      
std::cout<<"nCaptrued group 1 of first match: "<<vec_num[0][1]; 
std::cout<<"nCaptrued group 2 of first match: "<<vec_num[0][2]; 
std::cout<<"nTotal match of second match: "<<vec_num[1][0];
std::cout<<"nCaptrued group 1 of second match: "<<vec_num[1][1];
std::cout<<"nCaptrued group 2 of second match: "<<vec_num[1][2]; 

获取命名的子字符串/捕获的组:

jp::VecNas vec_nas;
count = 
jp::Regex("(?<word>\w+)\s*(?<digit>\d+)","m")
                         .initMatch()
                         .setSubject("I am 23, I am digits 10")
                         .setModifier("g")
                         .setNamedSubstringVector(&vec_nas)
                         .match();
std::cout<<"nCaptured group (word) of first match: "<<vec_nas[0]["word"];
std::cout<<"nCaptured group (digit) of first match: "<<vec_nas[0]["digit"];
std::cout<<"nCaptured group (word) of second match: "<<vec_nas[1]["word"];
std::cout<<"nCaptured group (digit) of second match: "<<vec_nas[1]["digit"];

遍历所有匹配项和子字符串:

//Iterating through numbered substring
for(size_t i=0;i<vec_num.size();++i){
    //i=0 is the first match found, i=1 is the second and so forth
    for(size_t j=0;j<vec_num[i].size();++j){
        //j=0 is the capture group 0 i.e the total match
        //j=1 is the capture group 1 and so forth.
        std::cout<<"nt("<<j<<"): "<<vec_num[i][j]<<"n";
    }
}

替换/替换示例:

std::cout<<"n"<<
///replace all occurrences of a digit with @
jp::Regex("\d").replace("I am the subject string 44", "@", "g");
///swap two parts of a string
std::cout<<"n"<<
jp::Regex("^([^t]+)t([^t]+)$")
             .initReplace()
             .setSubject("I am the subjecttTo be swapped according to tab")
             .setReplaceWith("$2 $1")
             .replace();

替换为匹配计算器:

jp::String callback1(const jp::NumSub& m, void*, void*){
    return "("+m[0]+")"; //m[0] is capture group 0, i.e total match (in each match)
}
int main(){
    jp::Regex re("(?<total>\w+)", "n");
    jp::RegexReplace rr(&re);
    String s3 = "I am ঋ আা a string 879879 fdsjkll ১ ২ ৩ ৪ অ আ ক খ গ ঘ আমার সোনার বাংলা";
    rr.setSubject(s3)
      .setPcre2Option(PCRE2_SUBSTITUTE_GLOBAL);
    std::cout<<"nn### 1n"<<
            rr.nreplace(jp::MatchEvaluator(callback1));
            //nreplace() treats the returned string from the callback as literal,
            //while replace() will process the returned string
            //with pcre2_substitute()
    #if __cplusplus >= 201103L
    //example with lambda
    std::cout<<"nn### Lambdan"<<
            rr.nreplace(
                jp::MatchEvaluator(
                    [](const jp::NumSub& m1, const jp::MapNas& m2, void*){
                        return "("+m1[0]+"/"+m2.at("total")+")";
                    }
                ));
    #endif
    return 0;
}

您可以在此处阅读完整的文档。

如果有人想使用visual studio 构建库

  1. 从网站下载pcre2(http://www.pcre.org/)
  2. 在Visual Studio 2015中(可能还有其他版本(,创建一个空项目"Win32项目",并将其称为pcre2
  3. 将\pcre2\src\中的所有文件复制到新创建的空项目中
  4. 添加"NON-AUTOTOOLS-BUILD"中列出的所有文件(位于基本文件夹中(
    • pcre2_auto_possess.c
    • pcre2_chartables.c
    • pcre2_compile.c
    • pcre2_config.c
    • 等等
  5. 将文件config.h.generic重命名为configuration.h
  6. 将config.h文件添加到项目中
  7. 在项目中,选择所有*.c文件Go Properties>c/c++>Precompiled Header>"Not Using Precompileed Header">
  8. 选择项目,转到属性>预处理器>预处理器定义,然后选择下拉列表,然后添加。。。
    • PCRE2_CODE_UNIT_WIDTH=8
    • HAVE_CONFIG_H

编译并创建lib文件应该很好。

PCRE2_SPTR pattern = (PCRE2_SPTR)std::string("([a-z]+)|\s").c_str();

将此指针与任何PCRE函数一起使用将导致未定义的行为。临时std::stringpattern的定义结束时被破坏,导致pattern悬空。

我的建议是将pattern的类型更改为std::string,并在向PCRE函数传递参数时调用c_str()。这是C++11中一个非常快速的操作(并且您没有使用旧的GCC 4 ABI(。

还有一些用于PCRE的C++包装器可能会帮助您避免此类问题,并使PCRE更易于使用,但我不了解Windows支持的状态。

我不知道这是否仍然是你正在关注的东西。。。但以防万一,这有帮助吗?

来自pcre2api手册页:

在Windows环境中,如果要将应用程序静态链接到非dll PCRE2库,则必须在包含PCRE2.h之前定义PCRE2_STATIC。

您可以执行以下步骤:

  1. 下载并安装cmake
  2. 设置源文件夹位置和VS项目文件夹
  3. 点击配置并选择VS版本
  4. 配置过程完成后,您可以从列表中选择8、16和/或32位
  5. 按生成,然后打开项目文件夹中的VS解决方案文件。这将在VS中打开解决方案
  6. 大约有6个项目。突出显示pcre2._项目。转到首选项并确保输出文件是用于DLL的。对pcre2posix项目重复此步骤。然后将greptest设置为exe(可执行文件(,将另一个设置为可执行文件
  7. 此时,您可以尝试构建所有DLL,但可能需要首先构建DLL,因为可执行文件依赖于它们(或者更确切地说是它们的静态库(进行链接
  8. 在所有6个项目都成功构建后,您应该在调试或发布文件夹中拥有共享/静态库和测试程序

以下是查尔斯·托马斯答案的更多细节。。。

如果你从C++在Windows上使用它,并且你将PCRE2构建为一个静态库。。。在pcre2.h中,有一个。。。

#if defined(_WIN32) && !defined(PCRE2_STATIC)
#  ifndef PCRE2_EXP_DECL
#    define PCRE2_EXP_DECL  extern __declspec(dllimport)
#  endif
#endif

_定义WIN32是因为你在Windows上,但你需要在PCRE2.h的顶部定义PCRE2_STATIC,就像这样…

#define PCRE2_STATIC 1

这使得它将extern";C">,而不是extern __declspec(dllimport(,这样您就可以静态链接。