如何访问命令行参数?

shu*_*fan 147 command-line rust

锈教程并没有解释如何在命令行中带参数.fn main()在所有示例中仅显示空参数列表.

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

bar*_*jak 162

您可以使用std::env::argsstd::env::args_os函数访问命令行参数.两个函数都在参数上返回迭代器.前者迭代Strings(易于使用)但如果其中一个参数不是有效的unicode则会发生混乱.后者迭代OsStrings,从不恐慌.

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

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

use std::env;

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

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

use std::env;

fn main() {
    if let Some(arg1) = env::args().nth(1) {
        println!("The first argument is {}", arg1);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在crates.io找到用于解析命令行参数的库:

  • docopt:您只需编写帮助消息,并为您生成解析代码.
  • 拍手:您使用流畅的API描述要解析的选项.比docopt更快,并为您提供更多控制.
  • getopts:流行的C库的端口.更低级别甚至更多控制.
  • structopt:建立在拍手之上,它更符合人体工程学.

  • 上面的评论(@LeoCorrea/@ S4M)提到了答案的旧版本; 当前版本的答案包含最新信息. (6认同)
  • 同样生锈0.8你应该只使用`println(args [0])` (2认同)

Bur*_*hi5 22

Docopt也可用于Rust,它会根据用法字符串为您生成解析器.作为Rust的一个奖励,可以使用宏来自动生成结构并进行基于类型的解码:

docopt!(Args, "
Usage: cp [-a] SOURCE DEST
       cp [-a] SOURCE... DIR

Options:
    -a, --archive  Copy everything.
")
Run Code Online (Sandbox Code Playgroud)

你可以得到args:

let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
Run Code Online (Sandbox Code Playgroud)

README和文档有很多完整的工作示例.

免责声明:我是该图书馆的作者之一.


Tob*_*obu 12

Rust getoptgetopts包中解析了-style CLI参数.


mre*_*mre 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();
Run Code Online (Sandbox Code Playgroud)

您可以像这样访问您的参数:

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);
Run Code Online (Sandbox Code Playgroud)

(从官方文件复制)


Phi*_*lux 8

如果没有必要,我个人不喜欢在较小的项目中使用库,并且在 Rust 中解析命令行参数非常简单:

fn main() {
    let config: String;

    let mut args = env::args().skip(1);
    while let Some(arg) = args.next() {
        match &arg[..] {
            "-h" | "--help" => help(),
            "--version" => {
                println!("{} {}", prog().unwrap_or_default(), VERSION);
            }
            "-q" | "--quiet" => {
                println!("Quiet mode is not supported yet.");
            }
            "-v" | "--verbose" => {
                println!("Verbose mode is not supported yet.");
            }
            "-c" | "--config" => {
                if let Some(arg_config) = args.next() {
                    config = arg_config;
                } else {
                    panic!("No value specified for parameter --config.");
                }
            }
            _ => {
                if arg.starts_with('-') {
                    println!("Unkown argument {}", arg);
                } else {
                    println!("Unkown positional argument {}", arg);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了处理非字符串参数,您可以使用 String::parse() 方法尝试将给定字符串解析为指定类型:

"-s" | "--size" => {
    if let Some(arg_size) = arg_it.next() {
        size = arg_size
            .parse::<usize>()
            .expect("Size argument expects an integer value.");
    } else {
        panic!("No value specified for parameter size.");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想使用等号 ( =) 而不是空格来处理值,您可以在子句上方包含以下代码match并匹配键值:

let (key, value) = match arg.contains('=') {
    true => {
        let str_vec: Vec<&str> = arg.split('=').collect();
        (String::from(str_vec[0]), Some(String::from(str_vec[1])))
    },
    false => {
        (arg, None)
    }
};
Run Code Online (Sandbox Code Playgroud)


Nic*_*ick 5

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

fn main() {
  let args: ~[~str] = ::std::os::args();
  println(args[0]);
}
Run Code Online (Sandbox Code Playgroud)

看来 Rust 现在即使使用标准 I/O 仍然非常不稳定,所以这可能很快就会过时。