接受命令行参数
让我们创建一个新项目,一如既往地使用cargo new
.我们将我们的项目称为minigrep
以将其与grep
您可能已经拥有的工具
在您的系统上。
$ cargo new minigrep
Created binary (application) `minigrep` project
$ cd minigrep
第一个任务是制作minigrep
接受其两个命令行参数:该
文件路径和要搜索的字符串。也就是说,我们希望能够运行我们的
程序替换为cargo run
,两个连字符表示以下参数是
对于我们的计划而不是cargo
、要搜索的字符串以及
要搜索的文件,如下所示:
$ cargo run -- searchstring example-filename.txt
现在,由cargo new
无法处理参数 we
给我。crates.io 上的一些现有库可以提供帮助
编写一个接受命令行参数的程序,但因为你是
只需学习这个概念,我们自己就实现这个功能吧。
读取 Argument 值
要启用minigrep
要读取命令行参数的值,我们传递给
it,我们需要std::env::args
Rust 标准中提供的函数
图书馆。此函数返回传递的命令行参数的迭代器
自minigrep
.我们将在第 13 章中全面介绍迭代器。现在,您只需要了解有关迭代器的两个详细信息:迭代器
产生一系列值,我们可以调用collect
method
将其转换为包含所有元素的集合,例如 vector
iterator 生成。
示例 12-1 中的代码允许你的minigrep
程序读取任何命令
line 参数传递给它,然后将值收集到一个 vector 中。
use std::env; fn main() { let args: Vec<String> = env::args().collect(); dbg!(args); }
首先,我们将std::env
module 添加到作用域中,并使用use
声明,所以我们
可以使用其args
功能。请注意,std::env::args
函数为
嵌套在两个级别的模块中。正如我们在本章中讨论的那样
7,在所需功能为
嵌套在多个模块中,我们选择将父模块引入
scope 而不是函数。这样,我们可以轻松地使用其他功能
从std::env
.它也比添加use std::env::args
和
然后调用args
因为args
可能很容易
误认为是当前模块中定义的函数。
这args
函数和无效的 Unicode
请注意,std::env::args
如果任何参数包含 Invalid ,将 panic
Unicode 的。如果您的程序需要接受包含无效
Unicode 的std::env::args_os
相反。该函数返回一个迭代器
产生OsString
值而不是String
值。我们选择这样做
用std::env::args
这里为简单起见,因为OsString
值每
平台,并且比String
值。
在main
,我们调用env::args
,我们立即使用collect
将迭代器转换为包含生成的所有值的向量
由 iterator 创建。我们可以使用collect
函数创建多种
集合,因此我们显式地注释了args
来指定我们
想要一个字符串向量。尽管您很少需要在
锈collect
是您经常需要注释的一个函数,因为 Rust
无法推断所需的集合类型。
最后,我们使用 debug 宏打印向量。让我们尝试运行代码 首先没有参数,然后有两个参数:
$ cargo run
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.61s
Running `target/debug/minigrep`
[src/main.rs:5:5] args = [
"target/debug/minigrep",
]
$ cargo run -- needle haystack
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.57s
Running `target/debug/minigrep needle haystack`
[src/main.rs:5:5] args = [
"target/debug/minigrep",
"needle",
"haystack",
]
请注意,vector 中的第一个值为"target/debug/minigrep"
哪
是二进制文件的名称。这与
C,让程序在执行时使用调用它们时所用的名称。
如果需要,访问程序名称通常很方便
将其打印在消息中,或根据内容更改程序的行为
命令行别名用于调用该程序。但为了这个
Chapter 中,我们将忽略它并仅保存我们需要的两个参数。
将参数值保存在变量中
该程序当前能够访问指定为命令行的值 参数。现在我们需要将两个参数的值保存在变量中,以便 我们可以在程序的其余部分使用这些值。我们在 Listing 中这样做 12-2.
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let query = &args[1];
let file_path = &args[2];
println!("Searching for {query}");
println!("In file {file_path}");
}
正如我们在打印 vector 时所看到的,程序的名称占据了第一个
值args[0]
,因此我们从索引 1 开始参数。这
第一个参数minigrep
takes 是我们要搜索的字符串,因此我们放置了一个
对变量中第一个参数的引用query
.第二个参数
将是文件路径,因此我们将对第二个参数的引用放在
变量file_path
.
我们临时打印这些变量的值以证明代码是
按照我们的意图工作。让我们使用参数再次运行这个程序test
和sample.txt
:
$ cargo run -- test sample.txt
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep test sample.txt`
Searching for test
In file sample.txt
太好了,程序正在运行!我们需要的参数的值是 保存到正确的变量中。稍后我们将添加一些错误处理来 deal 在某些潜在的错误情况下,例如当用户提供 No 参数;现在,我们将忽略这种情况并致力于添加文件读取 功能。
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准