2013-03-25 135 views

回答

123

您可以通过使用std::env::argsstd::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库用于解析命令行参数:

  • docopt:你刚才写的帮助信息,并生成解析代码为你。
  • clap:你描述了你想用流利的API解析的选项。比docopt更快,让你更有把握。
  • getopts:流行的C库的端口。更低层次,甚至更多的控制。
+2

还有锈0.8你应该只使用'println(args [0])' – 2013-09-27 02:24:29

+4

上面的评论(@LeoCorrea/@ S4M)引用了老版本的答案;答案的当前版本包含最新的信息。 – Nickolay 2017-03-11 09:11:57

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") 
    } 
} 
10

锈有getopt说明式的CLI参数解析在getopts module

+2

网址更改:http://doc.rust-lang.org/getopts/index.html – drhodes 2014-06-27 04:00:25

+1

尽管此链接可能会回答问题,但最好在此处包含答案的重要部分,并提供供参考的链接。如果链接页面更改,则仅链接答案可能会失效。 - [来自评论](/ review/low-quality-posts/17893179) – 2017-11-09 15:47:33

3

从版本0.8/0.9,在函数参数)的正确路径(将::std::os::args,即:

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

看来,锈病仍相当波动,现在甚至标准IO,所以这可能会很快过时。

+0

感谢您的更新!猜测1.0发布后我将不得不重新考虑接受的答案。 – shutefan 2014-01-16 20:59:25

1

从较新的Rust版本(Rust> 0.10/11)开始,数组语法将不起作用。你将不得不使用get方法。

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

use std::os; 

fn main() { 
    let args = os::args(); 
    println!("{}", args.get(1)); 
} 

// Compile 
rustc args.rs && ./args hello-world // returns hello-world 
+0

这是陈旧的陈述。最新的Rust nightlies支持'vec's的索引语法。我想它在那里一个月左右。看[这个例子](http://is.gd/YRvx3C)。 – 2014-08-14 18:54:26

+0

语法快速移动,所以也许它再次改变...... – stormpat 2014-08-14 19:22:49

1

自从2013年5月加尔文回答以来,Rust已经发展。现在,人们会解析命令行参数与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); 
} 
+0

只是为了记录:'as_slice()'不再存在,应该使用'&args'来代替。 – 2016-10-13 19:15:37

18

Docopt也可用于除锈,这从使用字符串生成一个解析器为您服务。作为防锈奖金,宏可以用来自动生成结构,做类型的基于解码:

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有充足完整的工作例子。

声明:我是该库的作者之一。

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()全局函数的手段。另一种选择是用#![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模块似乎是一个更好的做事方式。为了完成,我发布了这个答案。

3

铁锈又改变了。 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(); 

拉斯特 - 学会拥抱变化的痛苦。

+8

您现在只需要执行'env :: args()。collect()'。 – Tshepang 2015-02-23 02:11:34

6

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

这就是clap-rs派上用场。
这感觉有点像从Python的argparse。 这里是它的外观像一个例子:

let matches = App::new("myapp") 
         .version("1.0") 
         .author("Kevin K. <[email protected]>") 
         .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); 

+1

我喜欢clap-rs让你在yaml文件中定义你的接口。此外,它产生了非常漂亮的使用语句。 – 2017-02-19 20:43:54

0

(从official documentation复制)还检查了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