Rust 学习笔记 20:项目实战二:构建 grep 命令行工具 (minigrep)
Rust 学习笔记 20:项目实战二:minigrep “UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity.” – Dennis Ritchie 到目前为止,我们已经学习了 Rust 的大部分核心特性。现在,让我们把它们串起来,复刻一个经典的命令行工具:grep。 我们的目标是创建一个 minigrep,它接受一个查询字符串和一个文件名,然后打印出文件中包含查询字符串的行。 1. 需求分析 用法: 1$ cargo run -- searchstring example-filename.txt 功能点: 读取命令行参数。 读取文件内容。 筛选包含关键词的行。 错误处理(用户没传参数?文件不存在?)。 关注点分离:main.rs 负责处理参数和系统调用,lib.rs 负责核心逻辑。 TDD:测试驱动开发。 环境变量:支持 IGNORE_CASE=1 进行大小写不敏感搜索。 2. 核心代码演进 我们将代码分为 main.rs 和 lib.rs。 2.1 参数解析与配置 在 src/lib.rs 中定义 Config 结构体: 1use std::env; 2 3pub struct Config { 4 pub query: String, 5 pub file_path: String, 6 pub ignore_case: bool, 7} 8 9impl Config { 10 pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> { 11 args.next(); // 也就是程序名,通常忽略 12 13 let query = match args.next() { 14 Some(arg) => arg, 15 None => return Err("Didn't get a query string"), 16 }; 17 18 let file_path = match args.next() { 19 Some(arg) => arg, 20 None => return Err("Didn't get a file path"), 21 }; 22 23 let ignore_case = env::var("IGNORE_CASE").is_ok(); 24 25 Ok(Config { 26 query, 27 file_path, 28 ignore_case, 29 }) 30 } 31} 注意这里使用了 impl Iterator,这样我们可以直接消费 env::args(),更加高效。 ...