C++ 正则表达式从大括号构建向量

C++ 正则表达式从大括号构建向量,c++,regex,parsing,c++11,C++,Regex,Parsing,C++11,我想转换一个std::字符串,例如: 转换为std::字符串对的std::vector,看起来像: std::vector<std::pair<std::string, std::string>> v = {{"1", "2"}, {"one", "two"}, {"123", "onetwothree"}}; // where, for instance v[0] == std::make_pair("1", "2"); // etc. 在这种情况下,使用std::r

我想转换一个std::字符串,例如:

转换为std::字符串对的std::vector,看起来像:

std::vector<std::pair<std::string, std::string>> v = {{"1", "2"}, {"one", "two"}, {"123", "onetwothree"}};
// where, for instance
v[0] == std::make_pair("1", "2"); // etc.

在这种情况下,使用std::regex可以最容易地解析原始std::string,但我不是regex专家或新手,更不用说std::regex专家了。这里有食谱吗?

匹配模式非常简单:\{\s*\w+\s*\,\s*\w+\s*\},所以我们只需要循环并组装所有匹配项。C++11使这一点非常简单。试一试:

std::string str = "{1, 2}, {one, two}, {123, onetwothree}";
std::vector<std::pair<std::string, std::string>> pairs;
std::regex exp(R"(\{\s*(\w+)\s*\,\s*(\w+)\s*\})");
std::smatch sm;
std::string::const_iterator cit = str.cbegin();
while (std::regex_search(cit, str.cend(), sm, exp)) {
    if (sm.size() == 3) // 3 = match, first item, second item
        pairs.emplace_back(sm[1].str(), sm[2].str());
    // the next line is a bit cryptic, but it just puts cit at the remaining string start
    cit = sm[0].second;
}

匹配模式非常简单:\{\s*\w+\s*\,\s*\w+\s*\},所以我们只需要循环并组装所有匹配。C++11使这一点非常简单。试一试:

std::string str = "{1, 2}, {one, two}, {123, onetwothree}";
std::vector<std::pair<std::string, std::string>> pairs;
std::regex exp(R"(\{\s*(\w+)\s*\,\s*(\w+)\s*\})");
std::smatch sm;
std::string::const_iterator cit = str.cbegin();
while (std::regex_search(cit, str.cend(), sm, exp)) {
    if (sm.size() == 3) // 3 = match, first item, second item
        pairs.emplace_back(sm[1].str(), sm[2].str());
    // the next line is a bit cryptic, but it just puts cit at the remaining string start
    cit = sm[0].second;
}
目前,它不能很好地与GCC一起工作,这里有一个boost版本,使用-lboost_regex编译

适合此情况,但默认情况下未启用

以下是原始帖子:

目前,它不能很好地与GCC一起工作,这里有一个boost版本,使用-lboost_regex编译

适合此情况,但默认情况下未启用

以下是原始帖子:


到目前为止,您已经尝试了什么?关于{1,{2,3}{{a,b}}}的情况如何?现在,我正在使用std::string自己的find方法手动执行此操作。作为一个不喜欢正则表达式的人,这似乎是一个很好的开始,但我发现的示例往往返回单个大括号匹配的内容,而不是遍历多个大括号匹配的内容。至于格式,它对{first,second},{third,fourth}等非常严格。它是一个字符串对列表,如果这更清楚的话。我在上找到的例子是正确的,但太琐碎了。我只是不知道如何把它扩展到更复杂的情况。如果这是最好的,我可以使用一些混合字符串/正则表达式解决方案。到目前为止,您已经尝试了什么?关于{1,{2,3}{{a,b}}}呢?现在,我正在使用std::string自己的find方法手动执行此操作。作为一个不喜欢正则表达式的人,这似乎是一个很好的开始,但我发现的示例往往返回单个大括号匹配的内容,而不是遍历多个大括号匹配的内容。至于格式,它对{first,second},{third,fourth}等非常严格。它是一个字符串对列表,如果这更清楚的话。我在上找到的例子是正确的,但太琐碎了。我只是不知道如何把它扩展到更复杂的情况。如果这是最好的,我可以使用一些混合字符串/正则表达式解决方案。我把这个放进去,它完全按照我想要的那样工作。我想我最大的问题是理解正则表达式如何知道寻找N个匹配项。我在玩基于搜索和其他人评论的其他想法,我很难得到比外部{}匹配集更多的东西。啊!所以正则表达式一次只匹配一个,但是字符串迭代器沿着字符串前进,寻找后面的匹配项。谢谢你的额外解释。我应该看看迭代器是如何被更紧密地使用的!我添加了一个关于它如何工作的解释——正则表达式不是匹配N个匹配项,而是匹配第一个匹配项。然后,我们使用迭代器对余数进行迭代。在一个循环中这样做可以让我们赢得每一场比赛。听起来很像doesI把它放进去的东西,它的工作方式和我想要的完全一样。我想我最大的问题是理解正则表达式如何知道寻找N个匹配项。我在玩基于搜索和其他人评论的其他想法,我很难得到比外部{}匹配集更多的东西。啊!所以正则表达式一次只匹配一个,但是字符串迭代器沿着字符串前进,寻找后面的匹配项。谢谢你的额外解释。我应该看看迭代器是如何被更紧密地使用的!我添加了一个关于它如何工作的解释——正则表达式不是匹配N个匹配项,而是匹配第一个匹配项。然后,我们使用迭代器对余数进行迭代。在循环中这样做可以让我们赢得每一场比赛。听起来很像
{1, 2}, {one, two}, {123, onetwothree}
^ iterator cit
-- regex_search matches "{1, 2}" sm[1] == "1", sm[2] == "2"

{1, 2}, {one, two}, {123, onetwothree}
      ^ iterator cit
-- regex_search matches "{one, two}" sm[1] == "one", sm[2] == "two"

{1, 2}, {one, two}, {123, onetwothree}
                  ^ iterator cit
-- regex_search matches "{123, onetwothree}" sm[1] == "123", sm[2] == "onetwothree"

{1, 2}, {one, two}, {123, onetwothree}
                                      ^ iterator cit
-- regex_search returns false, no match
#include <iostream>
#include <string>
#include <boost/regex.hpp>

using namespace std;

int main()
{
  string str = "{1, 2}, {one, two}, {123, onetwothree}";

  boost::regex pair_pat("\\{[^{}]+\\}");
  boost::regex elem_pat("\\s*[^,{}]+\\s*");

  boost::sregex_token_iterator end;

  for(boost::sregex_token_iterator iter(str.begin(), str.end(), pair_pat, 0);
      iter != end; ++iter) {

    string pair_str = *iter;
    cout << pair_str << endl;

    for (boost::sregex_token_iterator it(pair_str.begin(), pair_str.end(), elem_pat, 0);
         it != end; ++it)
      cout << *it << endl;
  }

  return 0;
}