我有以下std::string
:
<lots of text not including "label A" or "label B">
label A: 34
<lots of text not including "label A" or "label B">
label B: 45
<lots of text not including "label A" or "label B">
...
我希望在label A
或label B
出现之后提取单个整数,并将它们放在相应的vector<int> a, b
中。一种简单但不优雅的方法是使用find("label A")
和find("label B")
并解析最先出的方法。是否有使用Spirit表达它的简洁方法?如何跳过除label A
或label B
之外的所有内容?
答案 0 :(得分:3)
你可以
omit [ eol >> *char_ - ("\nlabel A:") ] >> eol
示例: Live On Coliru
还有存储库中的seek[]
指令。以下内容相当于上述内容:
repo::seek [ eol >> &lit("int main") ]
这是一个解析原始样本的示例:
*repo::seek [ eol >> "label" >> char_("A-Z") >> ':' >> int_ ],
这将解析为std::vector<std::pair<char, int> >
而没有任何其他内容。
<强> On Coliru Too 强>:
#if 0
<lots of text not including "label A" or "label B">
label A: 34
<lots of text not including "label A" or "label B">
label B: 45
<lots of text not including "label A" or "label B">
...
#endif
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>
#include <fstream>
namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository::qi;
int main()
{
std::ifstream ifs("main.cpp");
ifs >> std::noskipws;
boost::spirit::istream_iterator f(ifs), l;
std::vector<std::pair<char, int> > parsed;
using namespace qi;
bool ok = phrase_parse(
f, l,
*repo::seek [ eol >> "label" >> char_("A-Z") >> ':' >> int_ ],
blank,
parsed
);
if (ok)
{
std::cout << "Found:\n";
for (auto& p : parsed)
std::cout << "'" << p.first << "' has value " << p.second << "\n";
}
else
std::cout << "Fail at: '" << std::string(f,l) << "'\n";
}
注意:
seek
确实公开了匹配的属性,这非常强大:
repo::seek [ eol >> "label" >> char_("ABCD") >> ':' ]
会吃掉&#39;标签,但标记字母('A'
,'B'
,'C'
或'D'
)作为属性。
跳过时的表现非常令人惊讶,请阅读文档中的警告http://www.boost.org/doc/libs/1_55_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/seek.html
输出
Found:
'A' has value 34
'B' has value 45