如何将 bash 脚本转换为 C++使用 boost::iostreams

发布于 2024-10-18 06:14:56 字数 2195 浏览 3 评论 0 原文

我正在尝试使用 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)什么是连接两个流的 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;
}

I'm trying to convert the following bash code into C++ using boost::iostreams:

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

I can open a file and decompress it:

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);

Then open an uncompressed file:

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

Now I'm a bit stuck, so here are my questions:

1) What's the boost::iostreams solution to concat the two streams?

2) How to output the result through a regex filter to emulate grep/sed?

As a result I'd like to have a an istream that i can copy to cout:

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

UPDATE complete solution using Hamigaki's concatenate:

/*
 * 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦屿孤独相伴 2024-10-25 06:14:56

1)我不知道boost中是否内置了任何东西,但这个类似乎正是你想要的: http://hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp

这里的问题是它期望可复制构造的设备连接,而链似乎不是可复制构造的。然而,我们可以使用 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

编辑:你现在似乎可以正常工作了。

1) I don't know if there's anything built into boost, but this class seems to be exactly what you want: http://hamigaki.sourceforge.jp/hamigaki/iostreams/concatenate.hpp

The catch here is that it expects CopyConstructible devices to concatenate and Chains seem to not be CopyConstructible. However, we can easily work around that using boost::ref. This code does (almost) what I understood you're asking:

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

I just used the regex filter instead of gzip, for testing.

2) boost::iostreams has a regex filter: http://www.boost.org/doc/libs/1_45_0/libs/iostreams/doc/classes/regex_filter.html

EDIT: You seem to have this working, now.

芯好空 2024-10-25 06:14:56

1) 在 boost 中不可用

Hamigakis 的串联 听起来很有趣,但我不知道如何使用它来组合两个 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);

1) Not available in boost

Hamigakis's concatenate sounds interesting, but I couldn't figure out how to use it to combine two boost::iostreams::chains. The code mentions it's meant for "concatenation of devices", so it might not be usable for chains. Please correct me if I'm wrong.

EDIT: updated my question with the complete solution.

2a) grep behavior (filter):

#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 behavior (search/replace):

#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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文