Использование pcre2 в проекте c++

Я смотрю на использование pcre2 в моем простом приложении c++ (я использую 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.ч. универсальный to pcre2.h

но затем я получаю ошибки компоновщика с неразрешенными внешними.

Я предполагаю, что мне нужно включить один или несколько файлов из источника в проект. Но я не хочу просто случайно добавлять файлы, не зная, что все это делает.

может ли кто-нибудь дать несколько простых шагов для успешного создания проекта с помощью pcre2?

обновление
Это не библиотека импорта выпуск, pcre2.h не поставляется с библиотекарем (не тот, который я вижу в их месте выпуска).

4 ответов


если вы не возражаете использовать обертку, вот мой:JPCRE2

вам нужно выбрать основной тип символа (char, wchar_t, char16_t, char32_t) в соответствии с классами строк, которые вы будете использовать (соответственно std::string, std::wstring, std::u16string, std::u32string):

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<<"\n\t("<<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 subject\tTo be swapped according to tab")
             .setReplaceWith(" ")
             .replace();

заменить на Match Evaluator:

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<<"\n\n### 1\n"<<
            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<<"\n\n### Lambda\n"<<
            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 project" и назовите его pcre2.
  3. скопируйте все файлы в \pcre2\src\ во вновь созданный пустой проект.
  4. добавить все файлы, перечисленные в "NON-AUTOTOOLS-BUILD", (находится в базе папка)
    • pcre2_auto_possess.c
    • pcre2_chartables.c
    • pcre2_compile.c
    • pcre2_config.c
    • etc...
  5. переименовать файл конфигурации.ч. универсальный to конфигурации.h
  6. Добавить файл config.H файл в проект.
  7. в вашем проекте, выберите все *.c file Go Properties > C / C++ > предварительно скомпилированный заголовок > "не использовать предварительно скомпилированный заголовок"
  8. выберите в проекте перейдите в свойства > препроцессор > определение препроцессора и выберите раскрывающийся список, а затем добавьте...
    • PCRE2_CODE_UNIT_WIDTH=8
    • HAVE_CONFIG_H

Compile и файл lib должны быть созданы нормально.


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

использование этого указателя с любой из функций PCRE приведет к неопределенному поведению. The std::string временное разрушается в конце определения pattern, причинив pattern чтобы мотаться.

моя рекомендация-изменить pattern'ы типа std::string и звонок c_str() при передаче аргументов функции PCRE. Это очень быстрая операция в C++11 (и вы не используете старый GCC 4 ABI).

есть также несколько оболочек C++ для PCRE, которые может помочь вам избежать таких проблем и сделать PCRE проще в использовании, но я не статус поддержки Windows.


Я не знаю, если это все еще то, что вы смотрите или нет... но на всякий случай поможет ли это?

из pcre2api man page:

в среде Windows, Если вы хотите статически связать прикладную программу с библиотекой PCRE2 не dll, необходимо определить PCRE2_STATIC перед включением pcre2.h.