Rewriting grep in C++



所以我正在尝试编写一个与grep执行相同任务的程序。最后,我想要一个包含四个参数的程序,第二个参数是要搜索的内容,第三个参数是输入文件,第四个参数是输出文件。我想我已经很好地掌握了如何进行,但和往常一样,理论很容易,而实际的编程我都很困惑。基本上,在我现在的位置,我已经找到了文件,我正在尝试搜索它,并获得包含我正在搜索的内容的所有行,以及该编号的行。

我想用一个矢量来完成这个任务。我不完全确定如何进行。遍历并将每一行单独添加到向量中,然后遍历并挑选出那些包含所需字符串的行,并使用其数组位置作为行号,会更容易吗?我想有一种方法可以只将那些包含所需字符串的行添加到向量中,但我不确定如何获得行号。我已经开始过几次了,当我意识到一切都错了时,我就把我所说的抹去了。

这就是我现在的处境:

#include <iostream>
#include <regex>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
int main (int argc, char* argv[]){
// validate the command line info
if( argc < 2 ) {
    cout << "Error: Incorrect number of command line argumentsn"
            "Usage: grepn";
    return EXIT_FAILURE;
}
//Declare the arguments of the array
string query = argv[1]; 
string inputFileName = argv[2];
string outputFileName = argv [3];
// Validate that the file is there and open it
ifstream infile( inputFileName );
if( !infile ) {
    cout << "Error: failed to open <" << inputFileName << ">n"
            "Check filename, path, or it doesn't exist.n";
    return EXIT_FAILURE;
}
else{
vector<string> queries;

}
}
}

不需要使用向量。在我看来,您应该使用std::getline一次遍历输入文件一行,尝试将每一行与regex匹配,并立即输出成功的行。

实现一个完整grep的大部分复杂性都是处理几十个标志来修改它的工作方式。一个简化的版本不尝试支持这些,只在一组文件中搜索指定的模式,这可能非常简单。C++11版本大致如下:

#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <regex>
class line {
    std::string data;
public:
    operator std::string() const { return data; }
    friend std::istream &operator>>(std::istream &is, line &l) {
        return std::getline(is, l.data);
    }
};
void process(std::regex const &pattern, std::istream &file) {
    typedef std::istream_iterator<line> in;
    typedef std::ostream_iterator<std::string> out;
    std::copy_if(in(file), 
                in(), 
                out(std::cout, "n"), 
                [&](std::string const &s) {return std::regex_search(s, pattern);});
}
int main(int argc, char **argv) { 
    if (argc < 2) {
        std::cerr << "Usage: grep <pattern> [file specification]";
        return 1;
    }
    std::regex pattern(argv[1], std::regex::nosubs | std::regex::optimize);
    if (argc < 3)
        process(pattern, std::cin);
    else
        for (int i=2; i<argc; ++i) {
            std::ifstream infile(argv[i]);
            std::cout << "t-- " << argv[i] << " --n";
            process(pattern, infile);
        }
    return 0;
}

在类Unix系统上,您不必做任何特殊的事情来构建它。在Windows上,您需要链接到编译器提供的用于处理globbing的对象文件(例如,使用MS VC++的setargv.obj)。

最新更新