3

我正在尝试解析嘈杂的输入,理想情况下,我将能够查看一个节是否符合规则,以及它是否确实获得了我需要的数据并丢弃其余部分。

我想要的数据如下。

Event: Newstate
Channel: SIP/104-000001bb
ChannelState: 6
ChannelStateDesc: Up

我想确保 Event if 类型为新状态。

我需要通道状态。其余的我不关心(只是还)所以我想忽略它,我希望它灵活并接受重要内容之间的任何旧废话,真的我不想说忽略这条线,而是忽略事件和我捕获值的通道状态结束之间的任何内容。

到目前为止,我得到了:

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 Spirit 0x2020

4

1 回答 1

6

记住:Spirit 的解析器是贪婪的。这意味着如果你这样做qi::omit[ <something> ],它将继续省略字符,直到<something>不再满足。因为<something>是字面上的任何东西char_匹配任何字符,所以*char_匹配所有字符),它将吃掉整个字符串的其余部分。然后它将引发错误,因为它从未到达“ChannelState:”。

你这样做的方式根本行不通。你必须有一些切断开关来阻止*char_吃东西。

我不明白为什么您不只是将它们全部解析为 a 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。

于 2011-11-04T18:53:42.860 回答