【问题标题】:Boost regex expression capture提升正则表达式捕获
【发布时间】:2014-05-28 14:23:39
【问题描述】:

我的目标是使用 boost::regex_search 捕获一个整数。

#define BOOST_REGEX_MATCH_EXTRA

#include <boost\regex.hpp>
#include <iostream>

int main(int argc, char* argv[])
{
  std::string tests[4] = {
    "SomeString #222",
    "SomeString #1",
    "SomeString #42",
    "SomeString #-1"
  };

  boost::regex rgx("#(-?[0-9]+)$");

  boost::smatch match;

  for(int i=0;i< 4; ++i)
  {
    std::cout << "Test " << i << std::endl;

    boost::regex_search(tests[i], match, rgx, boost::match_extra);

    for(int j=0; j< match.size(); ++j)
    {
      std::string match_string;
      match_string.assign(match[j].first, match[j].second);
      std::cout << "    Match " << j << ": " << match_string << std::endl;
    }
  }

  system("pause");
}

我注意到每个正则表达式搜索都会产生两个匹配项。第一个是匹配的字符串,第二个是括号中的捕获。

Test 0
    Match 0: #222
    Match 1: 222
Test 1
    Match 0: #1
    Match 1: 1
Test 2
    Match 0: #42
    Match 1: 42
Test 3
    Match 0: #-1
    Match 1: -1

除非需要,否则文档不鼓励使用 BOOST_REGEX_MATCH_EXTRA。是否需要在括号内捕获单个匹配项,还是有其他方法?

【问题讨论】:

  • 如果您可以链接到文档中提到不鼓励使用 BOOST_REGEX_MATCH_EXTRA 的特定部分,那就太好了。还有另一种方法,但我更不鼓励使用括号(如果性能是原因)!
  • @Jerry “其他方式”可能会更好。您是否针对 OP 的情况对其进行了分析?
  • @sehe “其他”方式(单独使用正则表达式)总是性能较差,这是功能和性能之间的权衡。

标签: c++ regex boost boost-regex


【解决方案1】:

如果您想要更快的速度,也许 Boost Spirit 可以带来它,或者其他 Boost Xpressive。

两者都将从表达式模板生成代码。这意味着,除其他外,如果您不“吸收”任何属性值,则不会产生任何成本。

提升精神:

此解决方案仅适用于标题。它可能会变得更有效率,但这是一个开始:

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

int main()
{
    std::string const tests[] = {
        "SomeString #222",
        "SomeString #1",
        "SomeString #42",
        "SomeString #-1"
    };

    for(auto& input : tests)
    {
        int value;
        auto f(input.begin()), l(input.end());
        if (qi::phrase_parse(f, l,  // input iterators
                    qi::omit [ *~qi::char_('#') ] >> '#' >> qi::int_, // grammar
                    qi::space,      // skipper
                    value))         // output attribute
        {
            std::cout << "     Input '" << input << "' -> " << value << "\n";
        }
    }
}

Live On Coliru

增强 Xpressive

#include <boost/xpressive/xpressive_static.hpp>
#include <iostream>
namespace xp = boost::xpressive;

int main()
{
    std::string const tests[] = {
        "SomeString #222",
        "SomeString #1",
        "SomeString #42",
        "SomeString #-1"
    };

    for(auto& input : tests)
    {
        static xp::sregex rex = (xp::s1= -*xp::_) >> '#' >> (xp::s2= !xp::as_xpr('-') >> +xp::_d);

        xp::smatch what;

        if(xp::regex_match(input, what, rex))
        {
            std::cout << "Input '" << what[0] << " -> " << what[2] << '\n';
        }
    }
}

也看到 Live On Coliru

我有一种预感,Spirit 解决方案的性能会更高,并且更接近您想要的(因为它会解析通用语法并直接将其解析为您想要的数据类型)。

【讨论】:

  • 除了 Boost Spirit 解决方案之外,还添加了 Boost Xpressive 解决方案。
猜你喜欢
  • 2011-09-02
  • 2019-02-22
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多