【问题标题】:Using Boost Spirit to parse a text file while skipping large parts of it使用 Boost Spirit 解析文本文件,同时跳过大部分内容
【发布时间】:2014-03-26 04:39:54
【问题描述】:

我有以下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 Alabel B 之后提取单个整数,并将它们放在相应的vector&lt;int&gt; a, b 中。一种简单但不优雅的方法是使用 find("label A")find("label B") 并解析先到者。有没有用 Spirit 简洁的表达方式?除了label Alabel B,您如何跳过所有内容?

【问题讨论】:

    标签: c++ boost boost-spirit seek


    【解决方案1】:

    你可以

    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&lt;std::pair&lt;char, int&gt; &gt; 而没有其他任何内容。

    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";
    }
    

    注意事项:

    输出是

    Found:
    'A' has value 34
    'B' has value 45
    

    【讨论】:

    • 我已编辑以在您的实际样本数据上显示 seek 指令。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    相关资源
    最近更新 更多