# Rust Simple Grep 一个用 Rust 实现的简单的 grep,可以读取文件,匹配正则表达式。 ## 思路 代码思路: 使用 regex 正则表达式库,env 读取 args 命令行参数。第1个参数为文件,第2个参数为正则表达式。 将正则表达式匹配到的行输出,并高亮匹配到的内容。同时显示所在行数。 如果没有第二个正则表达式参数,直接输出文件内容。 最后显示找的几行,几个符合正则表达式的字符串。 ## 代码 Cargo.toml ```toml [package] name = "mygrep" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] regex = "1.5.5" ``` src/main.rs ```rust use regex::Regex; use std::env; use std::fs::File; use std::io::Read; fn main() { // ["D:\\rustcode\\grep\\target\\debug\\grep.exe", "1", "2", "3"] let args: Vec = env::args().collect(); let file_path = args.get(1); let regex = args.get(2); let ex = args.get(3); if ex.is_some() { red("Extra words will be ingroned!"); } match file_path { Some(path) => read_file(path, regex), None => { red("No file path provided"); green("Helper:\nmygrep "); } } } fn read_file(file_path: &str, regex: Option<&String>) { let file = File::open(file_path); match file { Ok(mut file) => { green(&format!("Reading {}", file_path)); let mut contents = String::new(); let mut sum_lines = 0; let mut sum_key = 0; file.read_to_string(&mut contents).unwrap(); match regex { Some(regex) => { let re = Regex::new(®ex.to_string()).unwrap(); let mut lines = contents.lines(); let mut k = 1; while let Some(line) = lines.next() { if re.is_match(line) { let mut ans = line.to_string(); for caps in re.captures_iter(line) { let from = caps.get(0).unwrap().as_str(); ans = ans.replace(from.clone(), &blue(from)); sum_key += 1; // println!("CAPS: {:?}", caps.get(0).unwrap().as_str()); } sum_lines += 1; println!("{}: {}", yellow(&k.to_string()), ans); } k += 1; } } None => { let mut k = 1; // println!("{}", contents); contents.lines().for_each(|line| { println!("{}: {}", yellow(&k.to_string()), line); k += 1; }); } } green(&format!("Found {} lines, Key nums: {}", sum_lines, sum_key)); } Err(e) => panic!("File Open Error: {}", e), } // println!("read {:?}", file_path); } fn red(msg: &str) { println!("\x1b[91m{}\x1b[0m", msg); } fn green(msg: &str) { println!("\x1b[92m{}\x1b[0m", msg); } fn yellow(msg: &str) -> String { format!("\x1b[93m{}\x1b[0m", msg) } fn blue(msg: &str) -> String { format!("\x1b[94m{}\x1b[0m", msg) } ``` ## 测试 没有进行单元测试,异常也是直接抛出。对这个程序影响不是很大。 test.txt ``` read bluetooth blur old false bluetooth bluetooth bluetoothbluetooth ``` {{< image src="https://cdn.ftls.xyz/images/2022/04/Snipaste_2022-04-11_09-12-00.png" caption="text.txt测试" >}} 将 grep 路径加入操作系统的环境变量,然后就可以在终端中正常使用了。下面测试正则表达式的支持情况。 测试文件: https://www.ftls.xyz/posts/eshaas/index.md 结果: {{< image src="https://cdn.ftls.xyz/images/2022/04/Snipaste_2022-04-11_09-09-12.png" caption="正则表达式匹配和显示" >}}