我想为我在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函数吗?
提前致谢.
您想查看已传递了多少命令行参数.如果只有一个,那么你假设你正在使用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)
您可以使用条件(使用argc和argvin 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)
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 库似乎包含对管道的内置支持