如何只使用split_regex一次?

时间:2014-12-26 03:37:12

标签: c++ boost

函数模板boost::algorithm::split_regex将单个字符串拆分为原始字符串的子字符串中的字符串,这些字符串与我们传递给split_regex的正则表达式模式相匹配。问题是:如何在匹配的第一个子字符串上只拆分一次?也就是说,有可能在split_regex首次分裂后停止吗?请参阅以下代码。

#include <boost/algorithm/string/regex.hpp>
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <iostream>
#include <locale>

int main(int argc, char *argv[])
{
    using namespace std;
    using boost::regex;
    locale::global(locale(""));
    // Create a standard string for experiment.
    string strRequestLine("Host: 192.168.0.1:12345");
    regex pat(R"(:\s*)", regex::perl | boost::regex_constants::match_stop);
    // Try to split the request line.
    vector<string> coll;
    boost::algorithm::split_regex(coll, strRequestLine, pat);
    // Output what we got.
    for (const auto& elt : coll)
        cout << boost::format("{%s}\n") % elt;
    // Exit the program.
    return 0;
}

在哪里修改代码以使输出像

{Host}
{192.168.0.1:12345}

而不是当前输出

{Host}
{192.168.0.1}
{12345}

有任何建议/提示吗?感谢。

请注意,我不会询问如何使用其他功能或模式。我问split_regex是否可能只拆分一次然后停止。因为regex对象似乎有能力在第一次匹配时停止,我想知道如果提供一些正确的标志,它可能会在第一次匹配时停止。

2 个答案:

答案 0 :(得分:0)

对于您的具体输入,似乎简单的解决方法是将模式更改为R"(:\s+)"。当然,这假设在Host:之后至少有一个空格,并且IP地址和端口之间没有空格。

另一种选择是不使用split_regex()而是使用std::regex_match()

#include <iostream>
#include <regex>
#include <string>

int main()
{
    std::string strRequestLine("Host: 192.168.0.1:12345");
    std::smatch results;
    if (std::regex_match(strRequestLine, results, std::regex(R"(([^:]*):\s*(.*))"))) {
        for (auto it(++results.begin()), end(results.end()); it != end; ++it) {
            std::cout << "{" << *it << "}\n";
        }
    }
}

答案 1 :(得分:0)

扩展我的评论:

  

您可能对我列出的第一个示例感兴趣 here small HTTP response headers parsing function。摘要:使用phrase_parse(f, e, token >> ':' >> lexeme[*(char_ - eol)], space, key, value)

这是一个简单的示例:

<强> Live On Coliru

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

namespace {
    typedef std::string::const_iterator It;

    // 2.2 Basic Rules (rfc1945)
    static const qi::rule<It, std::string()> rfc1945_token = +~qi::char_( " \t><@,;:\\\"/][?=}{:"); // FIXME? should filter CTLs
}

#include <iostream>

int main()
{
    std::string const strRequestLine("Host: 192.168.0.1:12345");
    std::string::const_iterator f(strRequestLine.begin()), l(strRequestLine.end());

    std::string key, value;
    if (qi::phrase_parse(f, l, rfc1945_token >> ':' >> qi::lexeme[*(qi::char_ - qi::eol)], qi::space, key, value))
        std::cout << "'" << key << "' -> '" << value << "'\n";
}

打印

'Host' -> '192.168.0.1:12345'