Rust实现grep命令行工具的方法

 更新时间:2022年07月26日 14:22:11   作者:归海十八刀  
这篇文章主要介绍了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实现AES加解密详解

    Rust实现AES加解密详解

    这篇文章主要为大家详细介绍了如何利用Rust语言实现AES加解密算法,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以了解一下
    2022-10-10
  • Rust可迭代类型迭代器正确创建自定义可迭代类型的方法

    Rust可迭代类型迭代器正确创建自定义可迭代类型的方法

    在 Rust 中, 如果一个类型实现了 Iterator, 那么它会被同时实现 IntoIterator, 具体逻辑是返回自身, 因为自身就是迭代器,这篇文章主要介绍了Rust可迭代类型迭代器正确创建自定义可迭代类型的方法,需要的朋友可以参考下
    2023-12-12
  • Rust 标准库的结构及模块路径详解

    Rust 标准库的结构及模块路径详解

    在 Rust 中,标准库提供了一组核心功能,以帮助开发者执行常见的编程任务,这个路径树可以作为参考,帮助你更好地理解 Rust 标准库的结构和模块之间的关系,本文介绍 Rust 标准库的结构,并提供相应的 use 路径,感兴趣的朋友一起看看吧
    2024-05-05
  • rust 创建多线程web server的详细过程

    rust 创建多线程web server的详细过程

    web server 中主要的两个协议是 http 和 tcp,tcp 是底层协议,http 是构建在 tcp 之上的,本篇文章重点给大家介绍rust 创建多线程web server的详细过程,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • Rust Atomics and Locks内存序Memory Ordering详解

    Rust Atomics and Locks内存序Memory Ordering详解

    这篇文章主要为大家介绍了Rust Atomics and Locks内存序Memory Ordering详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Rust使用libloader调用动态链接库

    Rust使用libloader调用动态链接库

    这篇文章主要为大家介绍了Rust使用libloader调用动态链接库示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Rust Option类型基本使用详解

    Rust Option类型基本使用详解

    Rust的Option是一种强大的类型,用于处理可能为空的情况,避免了许多空值引起的运行时错误,本文介绍Rust Option类型详解,感兴趣的朋友一起看看吧
    2024-02-02
  • Rust 实现 async/await的详细代码

    Rust 实现 async/await的详细代码

    异步编程在 Rust 中的地位非常高,很多 crate 尤其是多IO操作的都使用了 async/await,这篇文章主要介绍了Rust 如何实现 async/await,需要的朋友可以参考下
    2022-09-09
  • 深入了解Rust中的枚举和模式匹配

    深入了解Rust中的枚举和模式匹配

    这篇文章主要为大家详细介绍了Rust中的枚举和模式匹配的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • 使用systemd部署r-nacos的操作方法

    使用systemd部署r-nacos的操作方法

    r-nacos是一个用rust实现的nacos服务,我们用它平替java nacos以降低服务占用内存,提升服务的稳定性,这篇文章主要介绍了使用systemd部署r-nacos,需要的朋友可以参考下
    2024-03-03

最新评论