C++ 增强精神-跳过键值对之间不需要的行
我有一个键值对列表,由EOL分隔。 我让Boost Spirit为格式正确的行执行我想要的操作(即MyKey:MyValue\r\n MyKey2:MyValue2) 现在我的问题是,我想跳过不符合要求的行。 例如:C++ 增强精神-跳过键值对之间不需要的行,c++,boost,boost-spirit,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Spirit Qi,我有一个键值对列表,由EOL分隔。 我让Boost Spirit为格式正确的行执行我想要的操作(即MyKey:MyValue\r\n MyKey2:MyValue2) 现在我的问题是,我想跳过不符合要求的行。 例如: This is some title line! Key1:Value1 Some more gibberish to skip Key2:Value2 我想到了下面的代码,我认为它可以工作,但是结果是映射为空,解析失败 在我的KeyRule中,我添加了'-qi::eol',
This is some title line!
Key1:Value1
Some more gibberish to skip
Key2:Value2
我想到了下面的代码,我认为它可以工作,但是结果是映射为空,解析失败
- 在我的
中,我添加了'-qi::eol',以避免在遇到第一个KeyRule
分隔符之前占用无效行KeyValue
- 在my
中,两个ItemRule
都是可选的,PairRule
为1或更多,以处理多个特征线eol
:
。
一定要有优雅的东西
#include <iostream>
#include <string>
#include <map>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator, typename Skipper = qi::blank_type>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>(), Skipper> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {
ItemRule = -PairRule >> *(+qi::eol >> -PairRule) >> -qi::eol;
PairRule = KeyRule >> ':' >> ValueRule;
KeyRule = qi::raw[+(qi::char_ - ':' - qi::eol)];
ValueRule = qi::raw[+(qi::char_ - qi::eol)];
}
qi::rule<Iterator, std::map<std::string, std::string>(), Skipper> ItemRule;
qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> PairRule;
qi::rule<Iterator, std::string(), Skipper> KeyRule;
qi::rule<Iterator, std::string(), Skipper> ValueRule;
};
int main() {
const std::string input = " Line To Skip! \r\n My Key : Value \r\n My2ndKey : Long Value \r\n";
std::string::const_iterator iter = input.begin(), end = input.end();
KeyValueParser<std::string::const_iterator> parser;
typedef std::map<std::string, std::string> MyMap;
MyMap parsed_map;
bool result = qi::phrase_parse(iter, end, parser, qi::blank, parsed_map);
if (result && (iter == end)) {
std::cout << "Success." << std::endl;
for (MyMap::const_iterator pIter = parsed_map.begin(); pIter != parsed_map.end(); ++pIter) {
std::cout << "\"" << pIter->first << "\" : \"" << pIter->second << "\"" << std::endl;
}
} else {
std::cout << "Something failed. Unparsed: ->|" << std::string(iter, end) << "|<-" << std::endl;
}
getchar();
return 0;
}
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
模板
结构KeyValueParser:qi::grammar{
KeyValueParser():KeyValueParser::基本类型(ItemRule){
ItemRule=-PairRule>>*(+qi::eol>>-PairRule)>>-qi::eol;
PairRule=KeyRule>>':'>>ValueRule;
KeyRule=qi::raw[+(qi::char_-':'-qi::eol)];
ValueRule=qi::raw[+(qi::char_u2;-qi::eol)];
}
qi::规则项规则;
齐:治廉;
qi::规则键规则;
qi::规则值规则;
};
int main(){
const std::string input=“要跳过的行!\r\n我的键:值\r\n My2ndKey:Long值\r\n”;
std::string::const_迭代器iter=input.begin(),end=input.end();
键值分析器;
typedef std::map MyMap;
MyMap解析图;
bool result=qi::phrase_parse(iter,end,parser,qi::blank,parsed_map);
if(结果&(iter==end)){
std::cout我能想到的最优雅的方法是解析一个keyvalue对/optional/,然后是任何胡言乱语,直到行尾
你可以写:
ItemRule = -PairRule % (*~char_("\r\n") >> eol);
唯一需要注意的是,在乱七八糟的行中,将插入“默认”对(空键和值),因此您必须删除后期解析
同样的书写方式(但不那么优雅)是:
ItemRule = (hold[PairRule] | omit[ *~char_("\r\n") ]) % eol;
演示
这是一个完整的演示。注意,我还将skipper知识移到了语法中(这对于语法的正确操作至关重要)
最后,我使用BOOST_SPIRIT_DEBUG打印调试输出
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <map>
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct KeyValueParser : qi::grammar<Iterator, std::map<std::string, std::string>()> {
KeyValueParser() : KeyValueParser::base_type(ItemRule) {
using namespace qi;
ItemRule = skip(blank) [ -PairRule % (*~char_("\r\n") >> eol) ];
ItemRule = skip(blank) [ hold[PairRule] | omit[ *~char_("\r\n") ] ] % eol;
PairRule = KeyRule >> ':' >> ValueRule;
KeyRule = +~char_("\r\n:");
ValueRule = +~char_("\r\n");
BOOST_SPIRIT_DEBUG_NODES((ItemRule)(PairRule)(KeyRule)(ValueRule))
}
private:
qi::rule<Iterator, std::map<std::string, std::string>()> ItemRule;
qi::rule<Iterator, std::pair<std::string, std::string>(), qi::blank_type> PairRule;
// lexemes
qi::rule<Iterator, std::string()> KeyRule, ValueRule;
};
int main() {
const std::string input = R"(
Line To Skip!
My Key : Value
Some more gibberish to skip
My2ndKey : Long Value
)";
std::string::const_iterator iter = input.begin(), end = input.end();
KeyValueParser<std::string::const_iterator> parser;
std::map<std::string, std::string> parsed_map;
bool result = qi::parse(iter, end, parser, parsed_map);
if (result && (iter == end)) {
std::cout << "Success.\n";
// drop empty lines:
parsed_map.erase("");
for (auto& p : parsed_map)
std::cout << "\"" << p.first << "\" : \"" << p.second << "\"\n";
} else {
std::cout << "Something failed. Unparsed: ->|" << std::string(iter, end) << "|<-\n";
}
}
带有调试信息
<ItemRule>
<try>\n Line To Skip! \n M</try>
<PairRule>
<try>\n Line To Skip! \n M</try>
<KeyRule>
<try>\n Line To Skip! \n M</try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> Line To Skip! \n My</try>
<KeyRule>
<try>Line To Skip! \n My </try>
<success>\n My Key : Value \nS</success>
<attributes>[[L, i, n, e, , T, o, , S, k, i, p, !, ]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My Key : Value \nSo</try>
<KeyRule>
<try>My Key : Value \nSome</try>
<success>: Value \nSome more g</success>
<attributes>[[M, y, , K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Value \nSome more gib</try>
<success>\nSome more gibberish</success>
<attributes>[[V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\nSome more gibberish</success>
<attributes>[[[M, y, , K, e, y, ], [V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try>Some more gibberish </try>
<KeyRule>
<try>Some more gibberish </try>
<success>\n My2ndKey : Long </success>
<attributes>[[S, o, m, e, , m, o, r, e, , g, i, b, b, e, r, i, s, h, , t, o, , s, k, i, p]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My2ndKey : Long </try>
<KeyRule>
<try>My2ndKey : Long V</try>
<success>: Long Value \n</success>
<attributes>[[M, y, 2, n, d, K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Long Value \n</try>
<success>\n</success>
<attributes>[[L, o, n, g, , , , , V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\n</success>
<attributes>[[[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try></try>
<KeyRule>
<try></try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<success></success>
<attributes>[[[[], []], [[M, y, , K, e, y, ], [V, a, l, u, e, ]], [[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]]</attributes>
</ItemRule>
\n要跳过的行!\n M
\n要跳过的行!\n M
\n要跳过的行!\n M
要跳过的行!\n我的
要跳过的行!\n我的
\n我的密钥:值\n
[L,i,n,e,T,o,S,k,i,p,!,]
我的密钥:值\n否
我的密钥:值\n某些
:Value\n还有一些g
[M,y,K,e,y,]
值\n还有一些gib
\再胡说八道
[V,a,l,u,e,]
\再胡说八道
[M,y,K,e,y,,[V,a,l,u,e,]]
更多的胡言乱语
更多的胡言乱语
\n My2ndKey:长
[S,o,m,e,m,o,r,e,g,i,b,b,e,r,i,S,h,t,o,S,k,i,p]]
My2ndKey:长
My2ndKey:长V
:长值\n
[M,y,2,n,d,K,e,y,]
长值\n
\n
[L,o,n,g,,,,V,a,L,u,e,]
\n
[M,y,2,n,d,K,e,y,,[L,o,n,g,,,,V,a,L,u,e,]]
[M,y,K,e,y,],[V,a,l,u,e,],[M,y,2,n,d,K,e,y,],[l,o,n,g,,,V,a,l,u,e,]]
除了前导空格没有被修剪这一事实之外,这似乎是可行的。我以前在键/值规则上使用了qi::raw和空白skipper组合,但这似乎不再有效。知道吗?@XanderLo我不确定您的原始示例会如何修剪尾随空格(我不认为是这样)。我还没看过。不过你可以用这个装置:这是我最初用来修剪前导空格的解决方案,它工作得很好:你的装置似乎工作得很好,尽管有点复杂。@Xandero the wayraw[*(a-b-c)]
有点违反直觉。它会在c
之前修剪空格,但不会在b
之前修剪raw[*(a-(b | c))]
会在b
或c
之前修剪空格。
<ItemRule>
<try>\n Line To Skip! \n M</try>
<PairRule>
<try>\n Line To Skip! \n M</try>
<KeyRule>
<try>\n Line To Skip! \n M</try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> Line To Skip! \n My</try>
<KeyRule>
<try>Line To Skip! \n My </try>
<success>\n My Key : Value \nS</success>
<attributes>[[L, i, n, e, , T, o, , S, k, i, p, !, ]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My Key : Value \nSo</try>
<KeyRule>
<try>My Key : Value \nSome</try>
<success>: Value \nSome more g</success>
<attributes>[[M, y, , K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Value \nSome more gib</try>
<success>\nSome more gibberish</success>
<attributes>[[V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\nSome more gibberish</success>
<attributes>[[[M, y, , K, e, y, ], [V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try>Some more gibberish </try>
<KeyRule>
<try>Some more gibberish </try>
<success>\n My2ndKey : Long </success>
<attributes>[[S, o, m, e, , m, o, r, e, , g, i, b, b, e, r, i, s, h, , t, o, , s, k, i, p]]</attributes>
</KeyRule>
<fail/>
</PairRule>
<PairRule>
<try> My2ndKey : Long </try>
<KeyRule>
<try>My2ndKey : Long V</try>
<success>: Long Value \n</success>
<attributes>[[M, y, 2, n, d, K, e, y, ]]</attributes>
</KeyRule>
<ValueRule>
<try>Long Value \n</try>
<success>\n</success>
<attributes>[[L, o, n, g, , , , , V, a, l, u, e, ]]</attributes>
</ValueRule>
<success>\n</success>
<attributes>[[[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]</attributes>
</PairRule>
<PairRule>
<try></try>
<KeyRule>
<try></try>
<fail/>
</KeyRule>
<fail/>
</PairRule>
<success></success>
<attributes>[[[[], []], [[M, y, , K, e, y, ], [V, a, l, u, e, ]], [[M, y, 2, n, d, K, e, y, ], [L, o, n, g, , , , , V, a, l, u, e, ]]]]</attributes>
</ItemRule>