提升正则表达式捕获

时间:2014-04-14 14:49:46

标签: c++ regex boost boost-regex

我的目标是使用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。是否需要在括号内捕获单个匹配,还是有其他方式?

1 个答案:

答案 0 :(得分:0)

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

两者都将从表达式模板生成代码。其中包括,如果你不吸收&#34;任何属性值,都不会产生任何费用。

提升精神:

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

#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

Boost 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解决方案会更高效,并且接近您想要的(因为它解析一般语法并直接将其解析为您想要的数据类型)。