我想解析如下内容:
tag = value
tag2 = value2
tag3 = value3
放宽允许超过多行的值并忽略下一个标记的注释。通过不以注释标识符“#”开头并从新行开始来标识标记。所以这个:
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( );
}
}
请注意,我不要求将结果存储在当前使用的容器类型中。我可以切换到任何更合适的东西,除非我得到(注释,标记名,值)的集合。
答案 0 :(得分:0)
通常regexs add complexity to your code,但在这种情况下,似乎正则表达式将是最佳解决方案。像这样的正则表达式将捕获你的对的第一和第二部分:
(?:\s*#.*\n)*(\w+)\s*=\s*((?:[^#=\n]+(?:\n|$))+)
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;
}
这显然超出了原问题中的要求;解析标签和值而不是只是抓住线。这里有相当多的功能是C ++的新功能,所以如果有任何问题请在下面发表评论。