我正在尝试解析一个嘈杂的输入,理想情况下,我能够看到一个节是否与规则匹配,是否确实获得了我需要的数据并丢弃其余数据。
我想要的数据如下。
Event: Newstate
Channel: SIP/104-000001bb
ChannelState: 6
ChannelStateDesc: Up
我想确保Event if if new state。
我需要频道状态。其余的我不关心(刚才)所以我想忽略它,我希望它是灵活的,并接受重要的东西之间的任何旧垃圾,真的我不想说忽略这一行,而是忽略事件和信道状态结束之间的任何事情,我捕获值。
到目前为止,我有:
typedef boost::fusion::vector2<std::string, std::string> vect;
qi::rule<std::string::iterator, vect(), space> rule_ =
lit("Event: ") >> *char_("a-zA-Z") >>
qi::omit[ *char_ ] >>
"ChannelState: " >> *char_("0-9") >>
qi::omit[ *char_ ];
但是由于某种原因这不起作用,当我这样做时,我总是得到回报:
vect v;
bool r=qi::parse(it, str.end(), rule_, v);
编辑:Boost版本1.42编译器g ++ 4.4精神0x2020
答案 0 :(得分:6)
记住:Spirit的解析器很贪婪。这意味着,如果您执行qi::omit[ <something> ]
,则会在<something>
不再符合之前继续省略字符。由于<something>
字面上任何(char_
匹配任何字符,因此*char_
匹配所有字符),它将占用字符串的其余部分。然后它会引发错误,因为它从未进入“ChannelState:”。
你做这件事的方式根本行不通。你必须有一些切断开关来阻止*char_
吃掉所有东西。
我不明白你为什么不把它们全部解析成std::map
,而不是零碎地做。然后你可以挑选出你想要的元素。你说你还不想要一些元素,所以请忽略它们。
这将按如下方式完成:
//Includes
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
//Code
using namespace boost::spirit;
using ascii::char_;
using ascii::string;
qi::rule<std::string::iterator, std::pair<std::string, std::string>() > pair_rule =
*(char_ - ':') >> ':' >>
qi::omit[*ascii::space] >>
*(char_ - eol) >> (eol || eoi);
qi::rule<std::string::iterator, std::map<std::string, std::string>() > map_rule =
+pair_rule;
std::map<std::string, std::string> v;
bool r = qi::parse(test.begin(), test.end(), map_rule, v);
请注意,这适用于Boost 1.47。我怀疑它会在早期版本中失败。
Boost版本1.42编译器g ++ 4.4 Spirit 0x2020
那些相当古老。你应该考虑升级。 Boost现在高达1.47。