rust Help

Grep lite

一个简易版的 grep, 从命令行读取搜索关键词和文件路径, 在文件中搜索匹配中的行结果, 及其上下文

use std::error::Error; use std::fs::File; use std::io::{BufRead, BufReader}; use clap::{Arg, ArgMatches, Command}; use regex::Regex; fn create_args() -> ArgMatches { Command::new("grep-lite") .version("0.1.0") .about("searches for patterns") .arg( Arg::new("pattern") // .long("pattern") // .short('p') .help("The pattern to search for") .num_args(1) .required(true), ) .arg( Arg::new("file") .long("file") .short('f') .help("File to search") .num_args(1) .required(false), ) .get_matches() } fn get_contents_by_buffer<T>(mut buffer: T) -> Result<String, Box<dyn Error>> where T: BufRead + Sized, { let mut result = String::new(); loop { let len = buffer.read_line(&mut result)?; if len == 0 { break; } } Ok(result) } fn main() -> Result<(), Box<dyn Error>> { let args = create_args(); let pattern = args.get_one::<String>("pattern").unwrap(); let re = Regex::new(pattern)?; let default_input = "examples/grep-lite/grep-lite".to_string(); let input = args.get_one::<String>("file").unwrap_or(&default_input); dbg!(input); let f = File::open(input)?; let buffer = BufReader::new(f); let contents = get_contents_by_buffer(buffer)?; let ctx_lines = 2; let mut tags: Vec<usize> = vec![]; let mut ctx: Vec<Vec<(usize, String)>> = vec![]; for (i, line) in contents.lines().enumerate() { let contains_substring = re.find(line); if contains_substring.is_some() { tags.push(i); ctx.push(Vec::with_capacity(ctx_lines * 2 + 1)); } } if tags.is_empty() { println!("Unmatched!"); return Ok(()); } for (i, line) in contents.lines().enumerate() { for (j, tag) in tags.iter().enumerate() { let lower_bound = tag.saturating_sub(ctx_lines); let upper_bound = tag + ctx_lines; if i >= lower_bound && i <= upper_bound { ctx[j].push((i + 1, line.to_string())); } } } for local_ctx in &ctx { for (i, line) in local_ctx { println!("{i} {line:?}"); } } Ok(()) }
Last modified: 25 May 2024