Poradnik Rust nie wyjaśnia, w jaki sposób podjąć parametrów z linii poleceń. fn main()
jest wyświetlany tylko z pustą listą parametrów we wszystkich przykładach.
Jaki jest prawidłowy sposób uzyskiwania dostępu do parametrów wiersza poleceń main
?
Poradnik Rust nie wyjaśnia, w jaki sposób podjąć parametrów z linii poleceń. fn main()
jest wyświetlany tylko z pustą listą parametrów we wszystkich przykładach.
Jaki jest prawidłowy sposób uzyskiwania dostępu do parametrów wiersza poleceń main
?
Odpowiedzi:
Dostęp do argumentów wiersza poleceń można uzyskać za pomocą funkcji std::env::args
lub std::env::args_os
. Obie funkcje zwracają iterator po argumentach. Pierwsza iteruje po String
s (z którymi łatwo się pracuje), ale panikuje, jeśli jeden z argumentów nie jest poprawnym kodem Unicode. Ten ostatni powtarza OsString
si i nigdy nie panikuje.
Zauważ, że pierwszym elementem iteratora jest nazwa samego programu (jest to konwencja we wszystkich głównych systemach operacyjnych), więc pierwszy argument jest w rzeczywistości drugim iterowanym elementem.
Prostym sposobem radzenia sobie z wynikiem args
jest przekonwertowanie go na Vec
:
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() > 1 {
println!("The first argument is {}", args[1]);
}
}
Możesz użyć całego standardowego zestawu narzędzi iteratora do pracy z tymi argumentami. Na przykład, aby pobrać tylko pierwszy argument:
use std::env;
fn main() {
if let Some(arg1) = env::args().nth(1) {
println!("The first argument is {}", arg1);
}
}
Możesz znaleźć biblioteki na crates.io do analizowania argumentów wiersza poleceń:
Docopt jest również dostępny dla Rusta, który generuje parser na podstawie ciągu znaków użycia. Jako bonus w Rust można użyć makra do automatycznego generowania struktury i dekodowania na podstawie typu:
docopt!(Args, "
Usage: cp [-a] SOURCE DEST
cp [-a] SOURCE... DIR
Options:
-a, --archive Copy everything.
")
I możesz uzyskać argumenty za pomocą:
let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
README i dokumentacja zawierają wiele pełnych przykładów roboczych.
Zastrzeżenie: jestem jednym z autorów tej biblioteki.
Rust ma getopt
parsowanie argumentów CLI w stylu-stylu w skrzynce getopts .
Dla mnie getopts zawsze wydawały się zbyt niskie, a docopt.rs było zbyt magiczne. Chcę czegoś wyraźnego i prostego, co nadal zapewnia wszystkie funkcje, jeśli ich potrzebuję.
Tutaj przydaje się clap-rs .
To trochę jak argparse z Pythona. Oto przykład, jak to wygląda:
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();
Możesz uzyskać dostęp do swoich parametrów w następujący sposób:
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);
(Skopiowane z oficjalnej dokumentacji )
Od wersji 0.8 / 0.9 poprawna ścieżka do funkcji args () będzie wyglądać następująco ::std::os::args
:
fn main() {
let args: ~[~str] = ::std::os::args();
println(args[0]);
}
Wygląda na to, że Rust jest nadal dość niestabilny, nawet przy standardowym IO, więc może się dość szybko zdezaktualizować.
Rdza znowu się zmieniła. os::args()
jest przestarzały na korzyść std::args()
. Ale std::args()
nie jest tablicą, zwraca iterator . Możesz iterować po argumentach wiersza poleceń, ale nie możesz uzyskać do nich dostępu za pomocą indeksów dolnych.
http://doc.rust-lang.org/std/env/fn.args.html
Jeśli chcesz, aby argumenty wiersza poleceń były wektorami ciągów, zadziała to teraz:
use std::env;
...
let args: Vec<String> = env::args().map(|s| s.into_string().unwrap()).collect();
Rdza - naucz się przyjmować ból zmiany.
env::args().collect()
.
to, co powiedział @barjak, działa dla łańcuchów, ale jeśli potrzebujesz argumentu jako liczby (w tym przypadku uint), musisz przekonwertować w ten sposób:
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")
}
}
Sprawdź również 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);
}
Od nowszych wersji Rusta (Rust> 0,10 / 11) składnia tablicy nie będzie działać. Będziesz musiał użyć metody get.
[Edytuj] Składnia tablicy działa (ponownie) w nocy. Możesz więc wybrać między indeksem pobierającym lub indeksem tablicy.
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. Myślę, że jest tam przez miesiąc. Zobacz ten przykład .
Rust ewoluował od czasu odpowiedzi Calvina z maja 2013 r. Teraz można przeanalizować argumenty wiersza poleceń za pomocą 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()
już nie istnieje i &args
powinno być używane zamiast tego.
Rozdział książki Rust „No stdlib” opisuje, jak uzyskać dostęp do parametrów wiersza poleceń (w inny sposób).
// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
Teraz przykład ma również, #![no_std]
co, jak sądzę, oznacza, że normalnie biblioteka std miałaby prawdziwy punkt wejścia dla twojego pliku binarnego i wywołałaby funkcję globalną o nazwie main()
. Inną opcją jest „wyłączenie main
podkładki” za pomocą #![no_main]
. Co, jeśli się nie mylę, oznacza powiedzenie kompilatorowi, że przejmujesz pełną kontrolę nad sposobem uruchamiania programu.
#![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
}
Nie sądzę, żeby to był „dobry” sposób robienia rzeczy, jeśli chcesz tylko czytać argumenty wiersza poleceń. std::os
Moduł wspomniano w innych odpowiedzi wydaje się być o wiele lepszy sposób robienia rzeczy. W celu uzupełnienia zamieszczam tę odpowiedź.
println(args[0])