提升精神:解析输入的一部分

时间:2015-10-11 21:29:10

标签: c++ parsing boost-spirit

我有数千行输入,每行包含3个整数和一个逗号,并且看起来像这样:

5 6 10,
8 9 45,
.....

如何创建仅解析输入的某个部分的语法,例如前100行或1000行到1200行,并忽略其余部分。

我的语法目前看起来像这样:

qi::int_ >> qi::int_ >> qi::int_ >> qi::lit(",");

但显然它解析了整个输入。

2 个答案:

答案 0 :(得分:4)

你可以找到有趣的点并在那里解析100行。

关于如何从精神中跳过100行的草图:

<强> Live On Coliru

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <tuple>

namespace qi = boost::spirit::qi;

int main() {
    using It  = boost::spirit::istream_iterator;
    using Tup = std::tuple<int, int, int>;

    It f(std::cin >> std::noskipws), l;
    std::vector<Tup> data;

    using namespace qi;

    if (phrase_parse(f, l,
            omit [ repeat(100) [ *(char_ - eol) >> eol ] ] >> // omit 100 lines
            repeat(10) [  int_ >> int_ >> int_ >> ',' >> eol ], // parse 10 3-tuples
            blank, data))
    {
        int line = 100;
        for(auto tup : data)
            std::cout << ++line << "\t" << boost::fusion::as_vector(tup) << "\n";
    }

}

使用

等随机输入进行测试时
od -Anone -t d2 /dev/urandom -w6 | sed 's/$/,/g' | head -200 | tee log | ./test
echo ============== VERIFY WITH sed:
nl log | sed -n '101,110p'

它会打印预期的内容,例如:

101 (15400 5215 -20219)
102 (26426 -17361 -6618)
103 (-15311 -6387 -5902)
104 (22737 14339 16074)
105 (-28136 21003 -11594)
106 (-11020 -32377 -4866)
107 (-24024 10995 22766)
108 (3438 -19758 -10931)
109 (28839 22032 -7204)
110 (-25237 23224 26189)
============== VERIFY WITH sed:
   101    15400   5215 -20219,
   102    26426 -17361  -6618,
   103   -15311  -6387  -5902,
   104    22737  14339  16074,
   105   -28136  21003 -11594,
   106   -11020 -32377  -4866,
   107   -24024  10995  22766,
   108     3438 -19758 -10931,
   109    28839  22032  -7204,
   110   -25237  23224  26189,

答案 1 :(得分:2)

仅仅因为我想了解更多关于Spirit X3的信息,并且因为世界想要了解更多关于这个即将推出的库的版本,这里有一个更复杂的版本,它显示了根据某种表达式动态过滤行的方法。 / p>

在这种情况下,这些行由此处理程序处理:

auto handle = [&](auto& ctx) mutable {
    using boost::fusion::at_c;

    if (++line_no % 10 == 0)
    {
        auto& attr = x3::_attr(ctx);
        data.push_back({ at_c<0>(attr), at_c<1>(attr), at_c<2>(attr) });
    }
};

正如您所期望的那样,每10行都包括在内。

<强> Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

int main() {
    using It  = boost::spirit::istream_iterator;

    It f(std::cin >> std::noskipws), l;

    struct Tup { int a, b, c; };
    std::vector<Tup> data;

    size_t line_no = 0;

    auto handle = [&](auto& ctx) mutable {
        using boost::fusion::at_c;

        if (++line_no % 10 == 0)
        {
            auto& attr = x3::_attr(ctx);
            data.push_back({ at_c<0>(attr), at_c<1>(attr), at_c<2>(attr) });
        }
    };

    if (x3::phrase_parse(f, l, (x3::int_ >> x3::int_ >> x3::int_) [ handle ] % (',' >> x3::eol), x3::blank))
    {
        for(auto tup : data)
            std::cout << tup.a << " " << tup.b << " " << tup.c << "\n";
    }

}

打印例如。

g++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp -o test
od -Anone -t d2 /dev/urandom -w6 | sed 's/$/,/g' | head -200 | tee log | ./test
echo ============== VERIFY WITH perl:
nl log | perl -ne 'print if $. % 10 == 0'
-8834 -947 -8151
13789 -20056 -11874
6919 -27211 -19472
-7644 18021 13523
-20120 16923 -11419
27772 31149 14005
3540 4894 -24790
10698 10223 -30397
-22533 -32437 -13665
25813 3264 -16414
11453 11955 18268
5092 27052 17930
10915 6493 20432
-14380 -6085 -25430
18599 6710 17279
22049 22259 -32189
1048 14621 6452
-24996 10856 29429
3537 -26338 19623
-4117 6617 14009
============== VERIFY WITH perl:
    10    -8834   -947  -8151,
    20    13789 -20056 -11874,
    30     6919 -27211 -19472,
    40    -7644  18021  13523,
    50   -20120  16923 -11419,
    60    27772  31149  14005,
    70     3540   4894 -24790,
    80    10698  10223 -30397,
    90   -22533 -32437 -13665,
   100    25813   3264 -16414,
   110    11453  11955  18268,
   120     5092  27052  17930,
   130    10915   6493  20432,
   140   -14380  -6085 -25430,
   150    18599   6710  17279,
   160    22049  22259 -32189,
   170     1048  14621   6452,
   180   -24996  10856  29429,
   190     3537 -26338  19623,
   200    -4117   6617  14009,