用Rust实现grep操作

这次的Rust练习是写一个linux命令的grep的操作,代码中有详细的注释。
步骤:
1.接收命令行参数。
2.读取文件。
3.重构:改进模块和错误处理。
4.使用TDD(测试驱动开发)开发库功能。
5.使用环境变量。
6.将错误消息写入标准错误而不是标准输出。

//main.rs
use mingrep::Config;
use std::process;
use std::env;//迭代器有一个方法叫collect,可以将一系列值转化为一个集合。

fn main(){
    let args:Vec<String>=env::args().collect();
    let config=Config::new(&args).unwrap_or_else(|err|{
        eprintln!("Problem parseing arguments:{}",err);
        //使用cargo run >output.txt不会出现这些信息,这些错误信息会在终端显示,而不会出现在文件中。
        process::exit(1);
    });
    //使用结构体方法,new。
    //unwrap_or_else返回的是如果成功,则把Ok里的放到config。如果失败执行后面的闭包,参数为err的内容。
    //程序执行到exit会立即终止,退出,不会打印额外的内容。
    if let Err(e)=mingrep::run(config){
        eprintln!("Application error:{}",e);
        process::exit(1);
    }
    //就是个运行函数,如果错误则打印错误原因,没错误就不处理。
}
//lib.rs
use std::fs;
use std::error::Error;
use std::env;


pub struct Config{
    pub query:String,
    pub filename:String,
    pub case_sensitive:bool,
}
impl Config{
    pub fn new(args:&[String])->Result<Config,&'static str>{
        if args.len()<3{
            return Err("not enough arguments");
        }
        let query=args[1].clone();
        let filename=args[2].clone();
        //将两个变量放入结构体中,没有所有权是不行的,需要clone一下。
        let case_sensitive=env::var("CASE_INSENSITIVE").is_err();
        //这里的环境变量是通过加在cargo run前面的来实现。
        Ok(Config{query,filename,case_sensitive})
        //参数少了就返回Err里的字符串,成功就返回Ok里的Config。
    }
}
//返回的是:成功就返回空的元组,没有返回。失败返回动态错误类型,自己定义好的Trait。
pub fn run(config:Config)->Result<(),Box<dyn Error>>{
    let contents=fs::read_to_string(config.filename)?;
    //这里的?就是遇到错误不会发生panic,将错误返回给调用者来处理。
    //expect()返回的是result枚举,如果返回的是Ok,就把值取出放在content,如果返回Err,就执行expect
    let results=if config.case_sensitive{
        search(&config.query,&contents)
    }else{
        search_case_insensitive(&config.query, &contents)
    };
    //使用一个bool类型的配置项,选择是否区分大小写。
    for line in results{
        println!("{}",line);
    }
    Ok(())
}

//这里的生命周期是返回的str和contents有关,和query无关。
//区分大小写的匹配。
pub fn search<'a>(query:&str,contents:&'a str)->Vec<&'a str>{
    let mut results=Vec::new();
    for line in contents.lines(){
        if line.contains(query){
            results.push(line);
        }
    }
    results
}
//不区分大小写的
pub fn search_case_insensitive<'a>(query:&str,contents:&'a str)->Vec<&'a str>{
    let mut results=Vec::new();
    let query=query.to_lowercase();
    for line in contents.lines(){
        if line.to_lowercase().contains(&query){
            results.push(line);
        }
    }
    results
}

#[cfg(test)]
mod tests{
    use super::*;
    #[test]
    fn case_sensitive(){
        let query="fas";
        let contents="\
Rust:
safe,fat,free
pick Fast.";
        assert_eq!(vec!["pick Fast."],search_case_insensitive(query,contents));
    }
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值