使用环境变量实现Rust程序中的不区分大小写搜索

步骤 1:编写失败的测试

我们遵循测试驱动开发(TDD)方法,首先编写一个测试来验证不区分大小写搜索功能。由于我们尚未实现该功能,因此这个测试会失败。以下是测试代码:

rust 复制代码
#[cfg(test)]
mod tests {
    use super::*;

    // 测试:区分大小写的搜索
    #[test]
    fn case_sensitive() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";

        // 期望返回大小写敏感的匹配结果
        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
    }

    // 测试:不区分大小写的搜索
    #[test]
    fn case_insensitive() {
        let query = "rUsT";  // 查询字符串的大小写不一致
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

        // 期望返回不区分大小写的匹配结果
        assert_eq!(
            vec!["Rust:", "Trust me."],
            search_case_insensitive(query, contents)
        );
    }
}

在上述代码中:

  • case_sensitive 测试验证了原始的区分大小写的搜索。
  • case_insensitive 测试验证了我们将在后面实现的不区分大小写的搜索。此时,由于我们还没有实现 search_case_insensitive 函数,编译将失败。

步骤 2:实现 search_case_insensitive 函数

为了实现不区分大小写的搜索,我们需要修改 search 函数,使其能够忽略大小写。以下是 search_case_insensitive 函数的实现:

rust 复制代码
// 不区分大小写的搜索函数
pub fn search_case_insensitive<'a>(
    query: &str,       // 查询字符串
    contents: &'a str, // 文件内容
) -> Vec<&'a str> {
    let query = query.to_lowercase(); // 将查询字符串转换为小写
    let mut results = Vec::new(); // 存储匹配结果

    // 遍历文件中的每一行
    for line in contents.lines() {
        // 将每一行转换为小写再进行比较
        if line.to_lowercase().contains(&query) {
            results.push(line); // 如果匹配,加入结果列表
        }
    }

    results // 返回匹配的行
}

代码解释:

  • query.to_lowercase() 将查询字符串转换为小写,以确保不区分大小写地进行匹配。
  • line.to_lowercase() 将每一行内容转换为小写,并检查是否包含查询字符串。

步骤 3:修改 run 函数

run 函数是程序的核心,它负责执行搜索并输出结果。我们需要修改 run 函数,使其根据 Config 结构体中的 ignore_case 字段来决定是使用区分大小写的 search 函数,还是不区分大小写的 search_case_insensitive 函数。

rust 复制代码
// 根据配置运行搜索
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
    let contents = fs::read_to_string(config.file_path)?; // 读取文件内容

    // 根据 ignore_case 字段决定使用哪种搜索
    let results = if config.ignore_case {
        search_case_insensitive(&config.query, &contents) // 不区分大小写的搜索
    } else {
        search(&config.query, &contents) // 区分大小写的搜索
    };

    // 打印匹配的行
    for line in results {
        println!("{line}");
    }

    Ok(())
}

代码解释:

  • Config 结构体包含一个 ignore_case 字段,用于控制是否启用不区分大小写的搜索。
  • 根据 ignore_case 的值,我们决定调用 search 还是 search_case_insensitive

步骤 4:获取环境变量

现在,我们需要从环境变量中获取 IGNORE_CASE 的值,来决定是否启用不区分大小写的搜索。我们使用 Rust 标准库中的 env 模块来访问环境变量。

rust 复制代码
use std::env;

impl Config {
    // 构建 Config 实例
    pub fn build(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let file_path = args[2].clone();

        // 检查环境变量 IGNORE_CASE 是否设置
        let ignore_case = env::var("IGNORE_CASE").is_ok(); // 如果环境变量存在,则启用不区分大小写的搜索

        Ok(Config {
            query,
            file_path,
            ignore_case,
        })
    }
}

代码解释:

  • 我们使用 env::var("IGNORE_CASE").is_ok() 来检查环境变量 IGNORE_CASE 是否被设置。如果设置了该环境变量,我们将 ignore_case 设置为 true,否则默认为 false

步骤 5:运行程序

现在,我们的程序已经支持根据环境变量来控制搜索模式。你可以通过以下命令来运行程序:

  1. 不使用环境变量,执行区分大小写的搜索:
bash 复制代码
$ cargo run -- to poem.txt
  1. 设置环境变量 IGNORE_CASE=1,启用不区分大小写的搜索:
bash 复制代码
$ IGNORE_CASE=1 cargo run -- to poem.txt

对于 PowerShell 用户,可以使用以下命令:

powershell 复制代码
PS> $Env:IGNORE_CASE=1; cargo run -- to poem.txt

总结

通过使用环境变量,我们成功地在Rust程序中实现了不区分大小写的搜索功能。这种方式让用户可以通过简单的环境变量配置来改变程序的行为,而不需要每次运行程序时都指定命令行参数。通过这种方法,我们可以在命令行工具中灵活地控制不同的搜索模式,使程序更加友好和易于配置。

在本教程中,我们:

  • 通过 TDD 编写了失败的测试,并逐步实现了功能。
  • 学会了如何使用 Rust 标准库中的 env 模块获取环境变量。
  • 通过环境变量控制程序行为,让命令行工具更加灵活。

希望通过这个示例,你对 Rust 中如何使用环境变量有所了解,并能够在自己的项目中灵活应用。

相关推荐
ROCKY_8172 分钟前
数据结构(九)——排序
数据结构·算法·排序算法
lkbhua莱克瓦247 分钟前
用C语言实现了——一个基于顺序表的插入排序演示系统
c语言·开发语言·数据结构·程序人生·github·排序算法·交互
软件派1 小时前
基于YOLO算法的目标检测系统实现指南
算法·yolo·目标检测
flying robot1 小时前
js在浏览器执行原理
开发语言·javascript·ecmascript
代码小将3 小时前
Leetcode209做题笔记
java·笔记·算法
dhxhsgrx4 小时前
PYTHON训练营DAY25
java·开发语言·python
Musennn4 小时前
leetcode 15.三数之和 思路分析
算法·leetcode·职场和发展
风逸hhh7 小时前
python打卡day25@浙大疏锦行
开发语言·python
刚入门的大一新生7 小时前
C++初阶-string类的模拟实现与改进
开发语言·c++
CM莫问7 小时前
<论文>(微软)避免推荐域外物品:基于LLM的受限生成式推荐
人工智能·算法·大模型·推荐算法·受限生成