如何访问命令行参数?

Rust教程没有解释如何从命令行获取参数。 在所有示例中, fn main()仅显示一个空参数列表。

main访问命令行参数的正确方法是什么?

您可以通过使用std::env::argsstd::env::args_os函数来访问命令行参数。 这两个函数都会在参数上返回一个迭代器。 前者遍历String (这很容易处理),但如果其中一个参数是无效的unicode恐慌。 后者迭代OsString s,永不恐慌。

请注意,迭代器的第一个元素是程序本身的名称(这是所有主要操作系统中的约定),所以第一个参数实际上是第二个迭代元素。

处理args结果的简单方法是将其转换为Vec

 use std::env; fn main() { let args: Vec<_> = env::args().collect(); if args.len() > 1 { println!("The first argument is {}", args[1]); } } 

您可以使用整个标准迭代器工具箱来处理这些参数。 例如,只检索第一个参数:

 use std::env; fn main() { if let Some(arg1) = env::args().nth(1) { println!("The first argument is {}", arg1); } } 

您可以在crates.io上find用于parsing命令行参数的库:

  • docopt :您只需编写帮助信息,并为您生成parsing代码。
  • clap :你描述你想用stream利的APIparsing的选项。 比docopt更快,给你更多的控制。
  • getopts :stream行的C库的端口。 更低层次,甚至更多的控制。

Rust也可以使用Docopt ,它从一个用法string为你生成一个parsing器。 作为Rust的一个奖励,一个macros可以被用来自动生成结构并且进行基于types的解码:

 docopt!(Args, " Usage: cp [-a] SOURCE DEST cp [-a] SOURCE... DIR Options: -a, --archive Copy everything. ") 

你可以得到的参数:

 let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit()); 

自述文件和文档有很多完整的工作示例。

免责声明:我是这个图书馆的作者之一。

生锈的getopt样式cli参数parsing在getopts模块中 。

对我来说,getopts总是觉得太低级,docopt.rs太神奇了。 我想要一些明确和直接的东西,如果我需要它们,仍然可以提供所有的function。

这是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); 

(从官方文件复制)

铁锈又改变了。 os::args()不推荐使用std::args() 。 但是std::args()不是一个数组,它返回一个迭代器 。 您可以迭代命令行参数,但不能使用下标访问它们。

http://doc.rust-lang.org/std/env/fn.args.html

如果你想把命令行参数作为一个string的vector,现在就可以工作了:

 use std::env; ... let args: Vec<String> = env::args().map(|s| s.into_string().unwrap()).collect(); 

生锈 – 学会拥抱变革的痛苦。

从版本0.8 / 0.9开始,函数args()的正确path是::std::os::args ,即:

 fn main() { let args: ~[~str] = ::std::os::args(); println(args[0]); } 

看起来,即使是标准的IO,Rust现在仍然很不稳定,所以这可能会很快过时。

@barjak说什么工作的string,但如果你需要参数作为一个数字(在这种情况下,一个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") } } 

作为更新的Rust版本(Rust> 0.10 / 11),数组语法不能工作。 你将不得不使用get方法。

[编辑]数组语法在夜间工作(再次)。 所以你可以在getter或array索引之间进行select。

 use std::os; fn main() { let args = os::args(); println!("{}", args.get(1)); } // Compile rustc args.rs && ./args hello-world // returns hello-world 

自从2013年5月Calvin的回答以来,Rust已经发展了。现在我们可以用as_slice()来parsing命令行参数:

 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); } 

Rust书中的“No stdlib”一章介绍了如何访问命令行参数(另一种方式)。

 // Entry point for this program #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } 

现在,这个例子也有#![no_std] ,我认为通常情况下,std库会为你的二进制文件创build一个真正的入口点,并调用一个名为main()的全局函数。 另一种select是用#![no_main] “禁用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 } 

如果你想要做的只是读命令行参数,我不认为这是一个“好”的做事方式。 其他答案中提到的std::os模块似乎是一个更好的方法。 为了完成,我发布了这个答案。

另外检查出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); } 

https://github.com/TeXitoi/structopt