如何在C++中实现grep,以便它与管道(stdin等)一起使用?

Adr*_*ian 1 c++ pipe

我想为我在Windows中使用的Shell实现grep(仅用于学习目的).
我知道grep具有以下语法:

grep pattern files
Run Code Online (Sandbox Code Playgroud)

所以我可以做一个像这样的功能:

int grep(string stringToMatch, string fileName) // just one file
{
   // search file for stringToMatch
   // print line containing stringToMatch
}
Run Code Online (Sandbox Code Playgroud)

我的困惑是,当我使用这样的管道时,grep应该如何工作:

ls | grep someword
Run Code Online (Sandbox Code Playgroud)

我实现了"ls"将所有输出放在一个向量中并返回,所以我想我的grep应该在向量中搜索结果.那么正确的grep函数应该怎么样呢?我需要2个grep函数吗?

提前致谢.

Fle*_*exo 6

您想查看已传递了多少命令行参数.如果只有一个,那么你假设你正在使用stdin而不是文件.

在C++中,可以通过std::istream在函数中使用对a的引用来抽象.在调用函数之前,您决定(并创建)一个(std::ifstream如果适用),或者以std::cin其他方式使用.

因此你的功能变成:

int grep(string stringToMatch, std::istream& in) // just one file
{
   // search file for stringToMatch
   // print line containing stringToMatch
}
Run Code Online (Sandbox Code Playgroud)

您可以使用条件(使用argcargvin main)来执行以下任一操作:

grep(string, std::cin);
Run Code Online (Sandbox Code Playgroud)

要么

std::ifstream file(fileName.c_str());
grep(string, file);
Run Code Online (Sandbox Code Playgroud)


seh*_*ehe 5

阅读UNIX 过滤器此处

Unix 过滤器通过标准输入和标准输出进行通信。即,在第二进程的标准输入上接收第一进程的标准输出。

标准输入和输出本质上是二进制/文本流

这个方法可以被链接起来。shell 通常是管理以下部分的一方: - 环境 - 进程的启动、监视和退出 - 互连

所以 0. 用户给出一个命令,例如 ls 1. shell 找到该命令,创建一个新进程,从终端连接 stdin 并从终端连接 stdout,2. 等待程序执行 3. 使用命令的结果设置环境子流程

如果你说你在向量中有 'ls' 输出,恐怕你还没有真正接近以真正的方式编写 shell

如果你想做一个没有进程管理、管道、重定向等所有特性的 shell,最有用的工具是 std::istream 和 std::ostream(或 Boost IOStreams 库)。

grep 的一个非常非常简单(真的非常愚蠢)的版本可能如下所示:

#include <iostream>
#include <string>

static bool is_match(const std::string& text, const std::string& pattern)
{
    // FIXME TODO use actual (posix?) regex, boost regex, regex++ or whatnot
    return std::string::npos != text.find(pattern);
}


int main(int argc, const char* argv[])
{
    switch(argc)
    {
        case 0: case 1:
            std::cerr << "specify the pattern" << std::endl;
            return 254;
        case 2:
            break;
        default:
            std::cerr << "not implemented" << std::endl;
            return 255;
    }
    const std::string pattern(argv[1]);

    std::string line;
    while (std::getline(std::cin, line))
    {
        if (is_match(line, argv[1]))
            std::cout << line << std::endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

存在更好的例子,例如这里,但从问题来看,我认为这是下一步的信息丰富的步骤;)

另请注意,Boost IOstreams 库似乎包含对管道的内置支持