В руководстве по Rust не объясняется, как получить параметры из командной строки. fn main()
отображается только с пустым списком параметров во всех примерах.
Как правильно получить доступ к параметрам командной строки из main
?
В руководстве по Rust не объясняется, как получить параметры из командной строки. fn main()
отображается только с пустым списком параметров во всех примерах.
Как правильно получить доступ к параметрам командной строки из main
?
Ответы:
Вы можете получить доступ к аргументам командной строки с помощью функций std::env::args
или std::env::args_os
. Обе функции возвращают итератор для аргументов. Первый итерирует по String
s (с которым легко работать), но паникует, если один из аргументов не является допустимым юникодом. Последний перебирает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 также доступен для Rust, который генерирует для вас парсер из строки использования. В качестве бонуса в Rust можно использовать макрос для автоматической генерации структуры и декодирования на основе типов:
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());
README и документация содержат множество полных рабочих примеров.
Отказ от ответственности: я один из авторов этой библиотеки.
У Rust есть getopt
синтаксический анализ CLI-стиля в ящике getopts .
Для меня getopts всегда чувствовал себя слишком низкоуровневым, и docopt.rs был слишком большим количеством магии. Я хочу что-то явное и простое, которое по-прежнему обеспечивает все функции, если они мне нужны.
Это где хлопать-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]);
}
Похоже, что Rust все еще довольно нестабилен, даже со стандартным вводом-выводом, поэтому он может устареть довольно быстро.
Ржавчина снова изменилась. 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();
Ржавчина - учись воспринимать боль перемен.
env::args().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")
}
}
Также проверьте 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);
}
В более новых версиях Rust (Rust> 0.10 / 11) синтаксис массива работать не будет. Вам придется использовать метод get.
[Редактировать] Синтаксис массива работает (снова) в ночное время. Таким образом, вы можете выбрать между индексом получателя или массива.
use std::os;
fn main() {
let args = os::args();
println!("{}", args.get(1));
}
// Compile
rustc args.rs && ./args hello-world // returns hello-world
Vec
s. Я предполагаю, что это там в течение месяца или около этого. Смотрите этот пример .
Rust развился после ответа Кальвина в мае 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);
}
as_slice()
больше не существует и &args
должен использоваться вместо этого.
В книге Rust «No 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
Модуль упоминается в других ответах , кажется, гораздо лучший способ делать вещи. Я выкладываю этот ответ ради завершения.
println(args[0])