Rust tutorial没有解释如何从命令行获取参数。 fn main()
仅在所有示例中显示为空参数列表。
从main
访问命令行参数的正确方法是什么?
答案 0 :(得分:156)
您可以使用std::env::args
或std::env::args_os
函数访问命令行参数。两个函数都在参数上返回迭代器。前者迭代String
s(易于使用)但如果其中一个参数不是有效的unicode则会发生混乱。后者迭代OsString
并且永远不会恐慌。
请注意,迭代器的第一个元素是程序本身的名称(这是所有主要操作系统中的约定),因此第一个参数实际上是第二个迭代元素。
处理args
结果的简便方法是将其转换为Vec
:
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() > 1 {
println!("The first argument is {}", args[1]);
}
}
您可以使用整个standard iterator toolbox来处理这些参数。例如,要仅检索第一个参数:
use std::env;
fn main() {
if let Some(arg1) = env::args().nth(1) {
println!("The first argument is {}", arg1);
}
}
您可以在crates.io上找到用于解析命令行参数的库:
答案 1 :(得分:21)
Docopt也可用于Rust,它会根据使用字符串为您生成解析器。作为Rust的一个奖励,可以使用宏来自动生成结构并进行基于类型的解码:
docopt!(Args, "
Usage: cp [-a] SOURCE DEST
cp [-a] SOURCE... DIR
Options:
-a, --archive Copy everything.
")
你可以通过以下方式获得args:
let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
README和documentation有很多完整的工作示例。
免责声明:我是该图书馆的作者之一。
答案 2 :(得分:11)
Rust在getopts crate中解析了getopt
样式的CLI参数。
答案 3 :(得分:8)
对我来说,傻瓜总是觉得太低级,而docopt.rs太神奇了。 我想要一些明确而直截了当的东西,如果我需要的话,仍然可以提供所有功能。
这是clap-rs派上用场的地方 感觉有点像Python的argparse。 以下是它的外观示例:
let matches = App::new("myapp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(Arg::with_name("CONFIG")
.short("c")
.long("config")
.help("Sets a custom config file")
.takes_value(true))
.arg(Arg::with_name("INPUT")
.help("Sets the input file to use")
.required(true)
.index(1))
.arg(Arg::with_name("debug")
.short("d")
.multiple(true)
.help("Sets the level of debugging information"))
.get_matches();
您可以像这样访问您的参数:
println!("Using input file: {}", matches.value_of("INPUT").unwrap());
// Gets a value for config if supplied by user, or defaults to "default.conf"
let config = matches.value_of("CONFIG").unwrap_or("default.conf");
println!("Value for config: {}", config);
答案 4 :(得分:3)
从版本0.8 / 0.9开始,函数args()的正确路径为::std::os::args
,即:
fn main() {
let args: ~[~str] = ::std::os::args();
println(args[0]);
}
看起来Rust现在仍然非常不稳定,即使是标准的IO,所以这可能会很快过时。
答案 5 :(得分:3)
Rust再次改变了。不推荐使用os::args()
,而是std::args()
。但std::args()
不是数组,它返回迭代器。您可以迭代命令行参数,但无法使用下标访问它们。
http://doc.rust-lang.org/std/env/fn.args.html
如果您希望命令行参数作为字符串向量,现在可以使用:
use std::env;
...
let args: Vec<String> = env::args().map(|s| s.into_string().unwrap()).collect();
Rust - 学会接受改变的痛苦。
答案 6 :(得分:2)
@barjak说什么适用于字符串,但如果你需要将参数作为数字(在这种情况下是一个uint),你需要像这样转换:
fn main() {
let arg : ~[~str] = os::args();
match uint::from_str(arg[1]){
Some(x)=>io::println(fmt!("%u",someFunction(x))),
None=>io::println("I need a real number")
}
}
答案 7 :(得分:1)
从较新的Rust版本(Rust&gt; 0.10 / 11)开始,数组语法不起作用。您将不得不使用get方法。
[编辑]数组语法在夜间工作(再次)。因此,您可以在getter或数组索引之间进行选择。
use std::os;
fn main() {
let args = os::args();
println!("{}", args.get(1));
}
// Compile
rustc args.rs && ./args hello-world // returns hello-world
答案 8 :(得分:1)
as_slice()
来解析命令行参数:
use std::os;
fn seen_arg(x: uint)
{
println!("you passed me {}", x);
}
fn main() {
let args = os::args();
let args = args.as_slice();
let nitems = {
if args.len() == 2 {
from_str::<uint>(args[1].as_slice()).unwrap()
} else {
10000
}
};
seen_arg(nitems);
}
答案 9 :(得分:1)
Rust book "No stdlib" chapter涵盖了如何访问命令行参数(另一种方式)。
// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
现在,该示例也有#![no_std]
,我认为这意味着通常,std库将具有二进制文件的真正入口点并调用名为main()
的全局函数。另一个选项是禁用main
垫片&#39;与#![no_main]
。如果我没弄错的话,那就是告诉编译器你正在完全控制程序的启动方式。
#![no_std]
#![no_main]
#[no_mangle] // ensure that this symbol is called `main` in the output
pub extern fn main(argc: isize, argv: *const *const u8) -> isize {
0
}
我不认为这是一个很好的&#39;如果你想做的就是阅读命令行参数。其他答案中提到的std::os
模块似乎是一种更好的做事方式。为了完成,我发布了这个答案。
答案 10 :(得分:0)
另请查看structopt:
extern crate structopt;
#[macro_use]
extern crate structopt_derive;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "example", about = "An example of StructOpt usage.")]
struct Opt {
/// A flag, true if used in the command line.
#[structopt(short = "d", long = "debug", help = "Activate debug mode")]
debug: bool,
/// An argument of type float, with a default value.
#[structopt(short = "s", long = "speed", help = "Set speed", default_value = "42")]
speed: f64,
/// Needed parameter, the first on the command line.
#[structopt(help = "Input file")]
input: String,
/// An optional parameter, will be `None` if not present on the
/// command line.
#[structopt(help = "Output file, stdout if not present")]
output: Option<String>,
}
fn main() {
let opt = Opt::from_args();
println!("{:?}", opt);
}