【问题标题】:Save/Serialize boost or std regexes保存/序列化 boost 或 std 正则表达式
【发布时间】:2013-09-11 23:09:56
【问题描述】:

是否可以对文件进行序列化/反序列化以及将正则表达式保存/加载到文件中?

我们有一个非常耗时的过程来构建一些正则表达式,我想知道我们是否可以通过保存和加载它们来节省一些时间。

【问题讨论】:

  • This questions 可能有一些有用的提示(我没有将其标记为重复,因为另一个问题是三年前的问题,并没有真正令人满意的答案 )。
  • 谢谢,是的。另一个问题很老了。
  • 我们在这里谈论多少个正则表达式?如果您为每个操作重新编译它们,从逻辑上讲这会降低性能,但是如果您编译它们一次,这应该不是问题。 (De)序列化其实是一件很棘手的事情,别指望它会在一分钟内实现。
  • 我说的太多了。我们只编译一次,但由于它们太多,这仍然是一个非常繁重的过程。
  • 由于正则表达式不再满足您的要求,您是否考虑过其他方法?像一个专用的编译器

标签: c++ regex boost std


【解决方案1】:

不,这可能是不可能的,因为无论如何它都需要你重新编译正则表达式。

但是,如果您使用 boost::xpressive,您可以在编译时通过正则表达式的表达式模板构造来编译正则表达式。这将使正则表达式的编译时间完全消失。

Boost Xpressive

但是,您使用过多时间的真正原因几乎可以肯定是您通过使用回溯正则表达式引擎不正确地使用正则表达式,即 IE。

RE2 是传统的自动机正则表达式引擎,不使用回溯,而是直接构造 NFA 或 DFA。如果您不使用反向引用或许多基于非正则表达式的“功能”,则使用 RE2 将在许多极端情况下显示速度提高一个数量级。

如果您正在使用这些功能,您应该意识到它们将严格控制您的匹配速度,并且几乎可以肯定它们是您寻求消除的减速的主要原因。

【讨论】:

    【解决方案2】:

    这对于 boost/stl 正则表达式类来说是很难实现的。问题在于所述类的内部结构。

    1. 实现如何存储类属性?按地址,价值?
    2. 编译器引入了哪些额外的填充(如果有)?
    3. 是否存在平台对齐问题?
    4. 等等……

    帮助说明问题的难度。尝试找出 C++ 类实例的大小。

    regex pattern( "^Corvusoft$" );
    
    printf( "%lu\n", sizeof( pattern ) );  //32
    
    regex alternative( "C" );
    
    printf( "%lu\n", sizeof( alternative ) );  //32
    

    替代方案 1

    在构建期间创建一个包含所需正则表达式和链接的库,或者通过dlopen api 动态打开和加载该库。然后,您将使用诸如prelink 之类的工具来确保它们已经在内存中;预编译。

    替代方案 2

    使用 C regex.h。

    您可以遍历 regex_t POD 结构并将其内容写入二进制或内存映射文件。以后您可以将这些数据值映射回新的 regex_t 结构,从而完全避免重新编译正则表达式。

    #include <regex.h>
    
    regex_t pattern;
    int result = 0;
    
    result = regcomp( &pattern, "^Corvusoft$", 0 );
    
    if ( result )
    {
       fprintf( stderr, "Failed to compile regular expression pattern\n" );
    }
    
    TODO: walk structure and write to binary/memory mapped file.
    

    替代方案 3

    听从@Alice 的建议并使用Boost.Xpressive

    【讨论】:

    • 感谢您的回答,但我很难理解您的第一个解决方案。 “预编译的正则表达式”是什么意思? afaik,boost 和 std 正则表达式都是运行时。
    • 我觉得他有点糊涂了;要使该解决方案起作用,您仍然需要在编译时生成正则表达式,这需要手动正则表达式或 Xpressive。
    • 我希望我的编辑澄清了“替代解决方案 1”。
    【解决方案3】:

    可以序列化一个 boost::regex:

    #include <string>
    #include <iostream>
    #include <sstream>
    
    #include <boost/regex.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/split_free.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/archive/text_oarchive.hpp>
    
    namespace boost
    {
      namespace serialization
      {
        template<class Archive, class charT, class traits>
        inline void save(Archive & ar, 
                         const boost::basic_regex<charT, traits> & t, 
                         const unsigned int /* file_version */)
        {
          std::basic_string<charT> str = t.str();
          typename boost::basic_regex<charT, traits>::flag_type flags = t.flags();
    //      typename boost::basic_regex<charT, traits>::locale_type loc = t.getloc();
          ar & str;
          ar & flags;
    //      ar & loc;
        }
    
        template<class Archive, class charT, class traits>
        inline void load(Archive & ar, 
                         boost::basic_regex<charT, traits> & t, 
                         const unsigned int /* file_version */)
        {
          std::basic_string<charT> str;
          typename boost::basic_regex<charT, traits>::flag_type flags;
    //      typename boost::basic_regex<charT, traits>::locale_type loc;
          ar & str;
          ar & flags;
    //      ar & loc;
          t.assign(str, flags);
    //      t.imbue(loc);
        }
    
        template<class Archive, class charT, class traits>
        inline void serialize(Archive & ar, 
                              boost::basic_regex<charT, traits> & t, 
                              const unsigned int file_version)
        {
          boost::serialization::split_free(ar, t, file_version);
        }
      }
    }
    
    int main(int argc, char ** argv)
    {
      std::stringstream os;
    
      {
        boost::regex re("<a\\s+href=\"([\\-:\\w\\d\\.\\/]+)\">");
        boost::archive::text_oarchive oar(os);
        oar & re;
      }
    
      os.seekg(std::ios_base::beg);
    
      boost::regex re;
      boost::cmatch matches;
      boost::archive::text_iarchive iar(os);
    
      iar & re;
    
      boost::regex_search("<a href=\"https://stackoverflow.com/questions/18752807/save-serialize-boost-or-std-regexes\">example</a>", matches, re);
    
      std::cout << matches[1] << std::endl;
    
    }
    

    但这并不意味着与从字符串重构正则表达式相比,您将获得任何性能提升。

    注意:为简单起见,我省略了 std::locale 内容

    【讨论】:

      猜你喜欢
      • 2011-05-28
      • 1970-01-01
      • 2022-06-13
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      相关资源
      最近更新 更多