如何访问命令行参数?
Rust教程没有解释如何从命令行获取参数。 在所有示例中, fn main()
仅显示一个空参数列表。
从main
访问命令行参数的正确方法是什么?
您可以通过使用std::env::args
或std::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); }