Как получить доступ к параметрам командной строки?
The учебник Руст не объясняет, как принять параметры из командной строки. fn main()
отображается только с пустым списком параметров во всех примерах.
Что такое правильный способ доступа к параметрам командной строки main
?
11 ответов:
вы можете получить доступ к аргументам командной строки с помощью тега
std::env::args
илиstd::env::args_os
функции. Обе функции возвращают итератор над аргументами. Первый перебираетString
s (с которыми легко работать), но паникует, если один из аргументов не является допустимым 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 для разбора командной строки аргументы:
- docopt: вы просто пишете сообщение справки, и код разбора генерируется для вас.
- хлоп: вы описываете параметры, которые вы хотите проанализировать с помощью fluent API. Быстрее, чем docopt и дает вам больше контроля.
- getopts: порт популярной библиотеки C. Более низкий уровень и даже больше контроля.
- structopt: построенный поверх хлопка, это еще больше эргономичный в использовании.
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 и документация есть много полных рабочих примеров.
отказ от ответственности: я один из авторов этой библиотеки.
Руст использования getopt-стиле командной строки разбора аргумент в модуль getopts.
для меня getopts всегда чувствовал себя слишком низкоуровневым и docopt.rs было слишком много магии. Я хочу что-то явное и простое, что по-прежнему предоставляет все функции, если они мне нужны.
вот тут хлоп-РС приходит в сподручное.
Это немного похоже на argparse из Python. Вот пример того, как это выглядит: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);
(скопированный с официальный документация)
начиная с версии 0.8 / 0.9, правильный путь к функции args () будет
::std::os::args
, например:fn main() { let args: ~[~str] = ::std::os::args(); println(args[0]); }
Кажется, что ржавчина все еще довольно изменчива прямо сейчас даже со стандартным IO, поэтому это может стать устаревшим довольно быстро.
ржавчина снова изменилась.
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();
ржавчина-научитесь принимать боль изменение.
то, что сказал @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") } }
в новых версиях Rust (Rust > 0.10/11) синтаксис массива не будет работать. Вам придется использовать метод get.[Edit] синтаксис массива работает (снова) в ночное время. Таким образом, вы можете выбрать между геттером или индексом массива.
use std::os; fn main() { let args = os::args(); println!("{}", args.get(1)); } // Compile rustc args.rs && ./args hello-world // returns hello-world
ржавчина эволюционировала с момента ответа Кальвина с мая 2013 года. Теперь можно было бы разобрать аргументы командной строки с помощью
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); }
The книга ржавчины" нет stdlib " глава описано, как получить доступ к параметрам командной строки (другой способ).
// Entry point for this program #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 }
теперь в Примере также есть
#![no_std]
что, я думаю, означает, что обычно библиотека std будет иметь истинную точку входа для вашего двоичного файла и вызывать глобальную функцию с именемmain()
. Другой вариант - " отключитьmain
ШИМ с#![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 }
я не думаю, что это хороший способ делать вещи, если все вы хотите сделать, это прочитать аргументы командной строки. Элемент
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); }