@ -8,7 +8,7 @@
### 编写一个大小写不敏感 `search` 函数的失败测试
### 编写一个大小写不敏感 `search` 函数的失败测试
我们希望增加一个新函数 `search_case_insensitive` ,并将会在设置了 环境变量时调用它。这里将继续遵循 TDD 过程,其第一步是再次编写一个失败测试。我们将为新的大小写不敏感搜索函数新增一个测试函数,并将老的测试函数从 `one_result` 改名为 `case_sensitive` 来更清楚的表明这两个测试的区别,如示例 12-20 所示:
首先 我们希望增加一个新函数 `search_case_insensitive` ,并将会在环境变量有值 时调用它。这里将继续遵循 TDD 过程,其第一步是再次编写一个失败测试。我们将为新的大小写不敏感搜索函数新增一个测试函数,并将老的测试函数从 `one_result` 改名为 `case_sensitive` 来更清楚的表明这两个测试的区别,如示例 12-20 所示:
< span class = "filename" > 文件名: src/lib.rs< / span >
< span class = "filename" > 文件名: src/lib.rs< / span >
@ -38,7 +38,7 @@
注意 `query` 现在是一个 `String` 而不是字符串 slice, 因为调用 `to_lowercase` 是在创建新数据,而不是引用现有数据。如果查询字符串是 `"rUsT"` ,这个字符串 slice 并不包含可供我们使用的小写的 `u` 或 `t` ,所以必需分配一个包含 `"rust"` 的新 `String` 。现在当我们将 `query` 作为一个参数传递给 `contains` 方法时,需要增加一个 & 因为 `contains` 的签名被定义为获取一个字符串 slice。
注意 `query` 现在是一个 `String` 而不是字符串 slice, 因为调用 `to_lowercase` 是在创建新数据,而不是引用现有数据。如果查询字符串是 `"rUsT"` ,这个字符串 slice 并不包含可供我们使用的小写的 `u` 或 `t` ,所以必需分配一个包含 `"rust"` 的新 `String` 。现在当我们将 `query` 作为一个参数传递给 `contains` 方法时,需要增加一个 & 因为 `contains` 的签名被定义为获取一个字符串 slice。
接下来在检查每个 `line` 是否包含 `search` 之前增加了一个 `to_lowercase` 调用将他们都变 为小写。现在我们将 `line` 和 `query` 都转换成了小写,这样就可以不管查询的大小写进行匹配了。
接下来我们对每一 `line` 都调用 `to_lowercase` 将其转 为小写。现在我们将 `line` 和 `query` 都转换成了小写,这样就可以不管查询的大小写进行匹配了。
让我们看看这个实现能否通过测试:
让我们看看这个实现能否通过测试:
@ -54,7 +54,7 @@
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:here}}
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:here}}
```
```
这里增加了 ` case_sensitiv e` 字符来存放一个布尔值。接着我们需要 `run` 函数检查 `case_sensitive` 字段的值并使用它来决定是否调用 `search` 函数或 `search_case_insensitive` 函数,如示例 12-22 所示。注意这还不能编译:
这里增加了 ` ignore_ case` 字符来存放一个布尔值。接着我们需要 `run` 函数检查 `case_sensitive` 字段的值并使用它来决定是否调用 `search` 函数或 `search_case_insensitive` 函数,如示例 12-22 所示。注意这还不能编译:
< span class = "filename" > 文件名: src/lib.rs< / span >
< span class = "filename" > 文件名: src/lib.rs< / span >
@ -62,9 +62,9 @@
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:there}}
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-22/src/lib.rs:there}}
```
```
< span class = "caption" > 示例 12-22: 根据 `config. case_sensitiv e` 的值调用 `search` 或 `search_case_insensitive` </ span >
< span class = "caption" > 示例 12-22: 根据 `config. ignore_ case` 的值调用 `search` 或 `search_case_insensitive` </ span >
最后需要实际检查环境变量。处理环境变量的函数位于标准库的 `env` 模块中,所以我们需要在 *src/lib.rs* 的开头增加一个 `use std::env;` 行 将这个模块引入作用域中。接着在 `Config::new` 中 使用 `env` 模块的 `var` 方法来检查一个叫做 ` IGNORE_CAS E` 的环境变量,如示例 12-23 所示:
最后需要实际检查环境变量。处理环境变量的函数位于标准库的 `env` 模块中,所以我们需要在 *src/lib.rs* 的开头将这个模块引入作用域中。接着使用 `env` 模块的 `var` 方法来检查一个叫做 ` CASE_INSENSITIV E` 的环境变量,如示例 12-23 所示:
< span class = "filename" > 文件名: src/lib.rs< / span >
< span class = "filename" > 文件名: src/lib.rs< / span >
@ -74,11 +74,11 @@
< span class = "caption" > 示例 12-23: 检查叫做 `IGNORE_CASE` 的环境变量</ span >
< span class = "caption" > 示例 12-23: 检查叫做 `IGNORE_CASE` 的环境变量</ span >
这里创建了一个新变量 ` case_sensitiv e`。为了设置它的值,需要调用 `env::var` 函数并传递我们需要寻找的环境变量名称,`IGNORE_CASE`。`env::var` 返回一个 `Result` ,它在环境变量被设置时返回包含其值的 `Ok` 成员,并在环境变量未被设置时返回 `Err` 成员。
这里创建了一个新变量 ` ignore_ case`。为了设置它的值,需要调用 `env::var` 函数并传递我们需要寻找的环境变量名称,`IGNORE_CASE`。`env::var` 返回一个 `Result` ,它在环境变量被设置时返回包含其值的 `Ok` 成员,并在环境变量未被设置时返回 `Err` 成员。
我们使用 `Result` 的 `is_err` 方法来检查其是否是一个 error( 也就是环境变量未被设置的情况) , 这也就意味着我们 ** 需要** 进行一个大小写敏感搜索。如果`IGNORE_CASE` 环境变量被设置为任何值,`is_err ` 会返回 false 并将进行大小写不敏感搜索。我们并不关心环境变量所设置的 ** 值**,只关心它是否被设置了,所以检查 `is_ err ` 而不是 `unwrap` 、`expect` 或任何我们已经见过的 `Result` 的方法。
我们使用 `Result` 的 `is_err` 方法来检查其是否是一个 error( 也就是环境变量未被设置的情况) , 这也就意味着我们 ** 需要** 进行一个大小写敏感搜索。如果`IGNORE_CASE` 环境变量被设置为任何值,`is_ok ` 会返回 false 并将进行大小写不敏感搜索。我们并不关心环境变量所设置的 ** 值**,只关心它是否被设置了,所以检查 `is_ ok ` 而不是 `unwrap` 、`expect` 或任何我们已经见过的 `Result` 的方法。
我们将变量 ` case_sensitiv e` 的值传递给 `Config` 实例,这样 `run` 函数可以读取其值并决定是否调用 `search` 或者示例 12-22 中实现的 `search_case_insensitive` 。
我们将变量 ` ignore_ case` 的值传递给 `Config` 实例,这样 `run` 函数可以读取其值并决定是否调用 `search` 或者示例 12-22 中实现的 `search_case_insensitive` 。
让我们试一试吧!首先不设置环境变量并使用查询 `to` 运行程序,这应该会匹配任何全小写的单词 “to” 的行:
让我们试一试吧!首先不设置环境变量并使用查询 `to` 运行程序,这应该会匹配任何全小写的单词 “to” 的行:
@ -88,6 +88,10 @@
看起来程序仍然能够工作!现在将 `IGNORE_CASE` 设置为 `1` 并仍使用相同的查询 `to` 。
看起来程序仍然能够工作!现在将 `IGNORE_CASE` 设置为 `1` 并仍使用相同的查询 `to` 。
```console
$ IGNORE_CASE=1 cargo run to poem.txt
```
如果你使用 PowerShell, 则需要用两个命令来分别设置环境变量并运行程序:
如果你使用 PowerShell, 则需要用两个命令来分别设置环境变量并运行程序:
```console
```console
@ -97,9 +101,6 @@ PS> $Env:IGNORE_CASE=1; cargo run to poem.txt
这回应该得到包含可能有大写字母的 “to” 的行:
这回应该得到包含可能有大写字母的 “to” 的行:
```console
```console
$ (IGNORE_CASE=1; cargo run to poem.txt)
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep to poem.txt`
Are you nobody, too?
Are you nobody, too?
How dreary to be somebody!
How dreary to be somebody!
To tell your name the livelong day
To tell your name the livelong day
@ -108,6 +109,6 @@ To an admiring bog!
好极了,我们也得到了包含 “To” 的行!现在 `minigrep` 程序可以通过环境变量控制进行大小写不敏感搜索了。现在你知道了如何管理由命令行参数或环境变量设置的选项了!
好极了,我们也得到了包含 “To” 的行!现在 `minigrep` 程序可以通过环境变量控制进行大小写不敏感搜索了。现在你知道了如何管理由命令行参数或环境变量设置的选项了!
一些程序允许对相同配置同时使用参数 ** 和** 环境变量。在这种情况下,程序来决定参数和环境变量的优先级。作为一个留给你的测试,尝试通过一个命令行参数或一个环境变量来控制大小写不 敏感搜索。并在运行程序时遇到矛盾值时决定命令行参数和环境变量的优先级。
一些程序允许对相同配置同时使用参数 ** 和** 环境变量。在这种情况下,程序来决定参数和环境变量的优先级。作为一个留给你的测试,尝试通过一个命令行参数或一个环境变量来控制大小写敏感搜索。并在运行程序时遇到矛盾值时决定命令行参数和环境变量的优先级。
`std::env` 模块还包含了更多处理环境变量的实用功能;请查看官方文档来了解其可用的功能。
`std::env` 模块还包含了更多处理环境变量的实用功能;请查看官方文档来了解其可用的功能。