9

boost::iostreamsを使用して次のbashコードをC++に変換しようとしています。

#!/usr/bin/bash
(
    gzip -cd file1.ext.gz
    cat file2.ext
) | grep '^regex' # or sed 's/search/replace/'

ファイルを開いて解凍できます。

std::ifstream s("file.ext.gz", std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_istreambuf in;
in.push(boost::iostreams::gzip_decompressor());
in.push(s);

次に、非圧縮ファイルを開きます。

std::ifstream s2("file.ext", std::ios_base::in | std::ios_base::binary);

今、私は少し立ち往生しているので、ここに私の質問があります:

1)2つのストリームを連結するためのboost :: iostreamsソリューションは何ですか?

2)grep / sedをエミュレートするために正規表現フィルターを介して結果を出力するにはどうすればよいですか?

結果として、coutにコピーできるistreamが必要です。

boost::iostream::copy(result, std::cout);

Hamigakiの連結を使用して完全なソリューションを更新します。

/*
 * convert the following bash script into C++
 *
 * #!/bin/bash
 * (
 *     gzip -cd file1.ext.gz
 *     cat file2.ext
 * ) | grep '^filter' | 'sed s/search/replace/g'
 *
 */

#include <iostream>
#include <boost/bind.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/regex.hpp>
#include <boost/iostreams/filter/grep.hpp>
#include <boost/iostreams/copy.hpp>

// http://hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp
#include "concatenate.hpp"

namespace io = boost::iostreams;

int main(int argc, char const* argv[])
{
    io::file_source file1("file1.ext.gz");
    io::file_source file2("file2.ext");
    io::gzip_decompressor gzip;
    io::regex_filter sed(boost::regex("search"), "replace");
    io::grep_filter grep(boost::regex("^filter"));

    io::filtering_istreambuf in1(gzip | file1);
    io::filtering_istreambuf in2(file2);

    io::filtering_istreambuf combined(sed | grep | 
            hamigaki::iostreams::concatenate(
                boost::ref(in1),
                boost::ref(in2)
            )
        );

    io::copy(combined, std::cout);

    return 0;
}
4

2 に答える 2

3

1)Boostに組み込まれているものがあるかどうかはわかりませんが、このクラスはまさにあなたが望むもののようです:http: //hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp

ここでの落とし穴は、CopyConstructibleデバイスが連結することを期待しており、チェーンはCopyConstructibleではないように見えることです。ただし、boost::refを使用してこれを簡単に回避できます。このコードは、あなたが求めていることを(ほぼ)私が理解したことを実行します:

int main(int argc, char const* argv[])
{
  boost::iostreams::filtering_istreambuf in;
  boost::regex regex("search");
  boost::iostreams::regex_filter rf(regex, "replace");
  in.push(rf);

  boost::iostreams::file_source file1(argv[1]);
  in.push(file1);

  boost::iostreams::file_source file2(argv[2]);
  boost::iostreams::copy(hamigaki::iostreams::concatenate(boost::ref(in), file2), std::cout);

  return 0;
}

テストには、gzipの代わりに正規表現フィルターを使用しました。

2)boost :: iostreamsには正規表現フィルターがあります:http ://www.boost.org/doc/libs/1_45_0/libs/iostreams/doc/classes/regex_filter.html

編集:あなたは今、これが機能しているようです。

于 2011-02-22T01:20:21.257 に答える
0

1)ブーストでは使用できません

Hamigakisの連結は面白そうに聞こえますが、2つのboost :: iostreams::chainを組み合わせるためにそれを使用する方法を理解できませんでした。コードには、「デバイスの連結」を目的としているため、チェーンには使用できない可能性があります。私が間違っている場合は訂正してください。

編集:完全な解決策で私の質問を更新しました。

2a)grepの動作(フィルター):

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/grep.hpp>

boost::iostreams::filtering_istreambuf in;
boost::regex regex("^search")
boost::iostreams::grep_filter grep(regex);
in.push(grep);

2b)sedの動作(検索/置換):

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/regex.hpp>

struct formatter {
    std::string operator()(const boost::match_results<const char*>& match)
    {
        return str(boost::format("%s | %s") % match[2] % match[1]);
    }
};
boost::iostreams::filtering_istreambuf in;
boost::regex regex("^([a-z]+) ([0-9]+)");
boost::iostreams::regex_filter sed(regex, formatter());
in.push(sed);
于 2011-02-22T15:31:05.400 に答える