【问题标题】:How to parse string pairs over multiple lines?如何在多行上解析字符串对?
【发布时间】:2015-08-04 11:41:16
【问题描述】:

我想解析如下内容:

tag = value
tag2 = value2
tag3 = value3

放宽了允许值跨越多行并忽略下一个标签的 cmets。通过不以注释标识符“#”开始并从新行开始来标识标签。所以这个:

tag = value
  value continuation
tag2 = value2
  value continuation2
# comment for tag3
tag3 = value3

应该解析映射:

tag : "value\nvalue continuation"
tag2 : "value2\nvalue continuation2"
tag3 : "value3"

我怎样才能以干净的方式实现这一目标?我当前用于解析单行对的代码如下所示:

while( std::getline( istr, line ) )
{
  ++lineCount;
  if( line[0] == '#' )
    currentComment.push_back( line );
  else if( isspace( line[0]) || line[0] == '\0' )
    currentComment.clear( );
  else
  {
    auto tag = Utils::string::splitString( line, '=' );
    if( tag.size() != 2 || line[line.size() - 1] == '=')
    {
      std::cerr << "Wrong tag syntax in line #" << lineCount << std::endl;
      return nullptr;
    }
    tagLines.push_back( line );
    currentComment.clear( );
  } 
}

请注意,我不需要将结果存储在当前使用的容器类型中。我可以切换到任何更适合的东西,除非我得到一组(评论、标记名、值)。

【问题讨论】:

  • 你能像 C++ 那样添加一个“行分隔符”吗?如果您可以添加一些内容来实际标记表达式的结尾,例如;,那么您可以使用getline() 并将; 指定为分隔符。
  • @user1709708 你的标签总是一个字吗? cmets 是否可以放在一对中间,例如:“tag2 = value2\n# comment for tag3\n\tvalue continuation”?值延续是否总是缩进,对开始是否从不缩进?
  • 标签始终是一个单词,成对中间的 cmets 当前被解析为标签/值的一部分。所以这不需要支持,除非它很容易。是的,延续总是缩进,而对则不是。这就是我们目前区分两者的方式。同样,除非有一个更清洁、更简单的解决方案,否则我可以保持原样。我认为行分隔符影响太大,因为这会影响我们迄今为止使用的所有旧文件。

标签: c++ string parsing


【解决方案1】:

通常regexs add complexity to your code,但在这种情况下,正则表达式似乎是最好的解决方案。像这样的正则表达式将捕获您对的第一部分和第二部分:

(?:\s*#.*\n)*(\w+)\s*=\s*((?:[^#=\n]+(?:\n|$))+)

[Live example]

In order to use a regex_iterator on an istream you'll need to either slurp the stream or use boost::regex_iterator with the boost::match_partial flag.istream 已经变成了string input。此代码将提取对:

const regex re("(?:\\s*#.*\\n)*(\\w+)\\s*=\\s*((?:[^#=\\n]+(\\n|$))+)");

for (sregex_iterator i(input.cbegin(), input.cend(), re); i != sregex_iterator(); ++i) {
    const string tag = i->operator[](1);
    const string value = i->operator[](2);

    cout << tag << ':' << value << endl;
}

[Live example]

这明显超出了原题的要求;解析标签和值,而不是仅仅抓住行。这里有相当多的 C++ 新功能,所以如果有任何问题,请在下方评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 2020-02-06
    • 2012-05-13
    • 1970-01-01
    相关资源
    最近更新 更多