Rust Simple Grep
目录
警告
本文最后更新于 2024-02-24,文中内容可能已过时。
一个用 Rust 实现的简单的 grep,可以读取文件,匹配正则表达式。
思路
代码思路: 使用 regex 正则表达式库,env 读取 args 命令行参数。第1个参数为文件,第2个参数为正则表达式。
将正则表达式匹配到的行输出,并高亮匹配到的内容。同时显示所在行数。
如果没有第二个正则表达式参数,直接输出文件内容。
最后显示找的几行,几个符合正则表达式的字符串。
代码
Cargo.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
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<String> = 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 <file_path> <regex>");
}
}
}
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
将 grep 路径加入操作系统的环境变量,然后就可以在终端中正常使用了。下面测试正则表达式的支持情况。
欢迎赞赏~
赞赏