Rust实现grep命令行工具的方法
一、功能:
1、输入要查询的字符串
和文件名
,输出所有匹配的行的内容
2、如果设置环境变量IGNORE_CASE
,则grep匹配将忽略大小写
3、可使用 >
符号来重定向标准输出到指定文件中
二、介绍
2.1 使用到的知识:
- 读取命令行参数
- 读取文件内容
- 错误处理
- Test Driven Development(TDD)
- 使用环境变量控制不同行为
2.2 代码
1、main.rs
use std::env; use std::process; use minigrep::Config; fn main() { // let args: Vec<String> = env::args().collect(); // let query = &args[1]; // let filename = &args[2]; // let content = fs::read_to_string(filename).expect("You have a problem in read a file"); // println!("Filename: {}", filename); // println!("File content:\n{}", content); //refactoring after let args: Vec<String> = env::args().collect(); // let config = Config::new(&args); let config = Config::new(&args).unwrap_or_else(|err| { eprintln!("Problem parse arguments: {}", err); process::exit(1); }); println!("query: {}, filename: {}", config.query, config.filename); if let Err(e) = minigrep::run(config) { eprintln!("Application Error: {}", e); process::exit(1); } }
2、lib.rs
use std::error::Error; use std::fs; use std::env; pub struct Config { pub query: String, pub filename: String, pub ignore_case: bool, } impl Config { // fn new(args: &[String]) -> Config { // let query = args[1].clone(); // let filename = args[2].clone(); // Config {query, filename} // } pub fn new(args: &[String]) -> Result<Config, &'static str> { if args.len() < 3 { return Err("No enough arguments"); } let query = args[1].clone(); let filename = args[2].clone(); let ignore_case = env::var("IGNORE_CASE").is_ok(); Ok(Config{query, filename, ignore_case}) } } pub fn run(config: Config) -> Result<(), Box<dyn Error>> { let content = fs::read_to_string(config.filename)?; // println!("With text:\n{}", content); let result = if config.ignore_case { search_case_insensitive(&config.query, &content) } else { search(&config.query, &content) }; for line in result { println!("{}", line); } Ok(()) } pub fn search<'a>(query: &str, content: &'a str) -> Vec<&'a str> { let mut result = Vec::new(); for line in content.lines() { if line.contains(query) { result.push(line); } } result } pub fn search_case_insensitive<'a>(query: &str, content: &'a str) -> Vec<&'a str> { let mut result = Vec::new(); let query = query.to_lowercase(); for line in content.lines() { if line.to_lowercase().contains(&query) { result.push(line); } } result } #[cfg(test)] mod tests { use super::*; #[test] fn one_result() { let query = "xwp"; let content = "\ Hello,rust! xwp is handsome You know!"; assert_eq!(vec!["xwp is handsome"], search(query, content)); } #[test] fn case_insensitive() { let query = "xWp"; let content = "\ Hello,rust! xwp is handsome You KonW"; assert_eq!(vec!["xwp is handsome"], search_case_insensitive(query, content)); } }
三、使用
- 需要输入两个参数,第一个是query,第二个是filename,如果参数少于两个会报错。
- 如:
cargo run xwp xwphs.txt
,xwp是要查询的内容,xwphs.txt是文件。 - minigrep默认是大小写敏感的,可通过设置
IGNORE_CASE
环境变量,使得查询忽略大小写。
在powershell中设置临时环境变量如:$Env:IGNORE_CASE=1
,解除:Remove-Item Env:IGNORE_CASE
;在shell中直接:将IGNORE_CASE=1放在最开始
参数不足时,提示Problem parse arguments: No enough argumentss
设置环境变量后,不区分大小写,查询到了信息
到此这篇关于Rust实现grep命令行工具的文章就介绍到这了,更多相关Rust命令行工具内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Rust Atomics and Locks内存序Memory Ordering详解
这篇文章主要为大家介绍了Rust Atomics and Locks内存序Memory Ordering详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-02-02
最新评论