Komut satırı parametrelerine nasıl erişilir?


153

Pas öğretici komut satırından parametre alması nasıl açıklamıyor.fn main()tüm örneklerde yalnızca boş bir parametre listesiyle gösterilir.

Komut satırı parametrelerine erişmenin doğru yolu nedir main?

Yanıtlar:


168

Komut satırı bağımsız değişkenlerine std::env::argsveya std::env::args_osişlevlerini kullanarak erişebilirsiniz . Her iki işlev de argümanların üzerinde bir yineleyici döndürür. Birincisi Strings ( üzerinde çalışmak kolay) üzerinden yinelenir, ancak argümanlardan biri geçerli unicode değilse panikler. İkincisi OsStrings üzerinde yinelenir ve asla panik yapmaz.

Yineleyicinin ilk öğesinin programın adı olduğunu unutmayın (bu, tüm büyük işletim sistemlerinde bir kuraldır), bu nedenle ilk argüman aslında ikinci yinelenen öğedir.

Sonucu ele almanın kolay bir yolu, argsonu aşağıdakilere dönüştürmektir Vec:

use std::env;

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

Bu bağımsız değişkenlerle çalışmak için tüm standart yineleyici araç kutusunu kullanabilirsiniz. Örneğin, yalnızca ilk argümanı almak için:

use std::env;

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

Komut satırı bağımsız değişkenlerini ayrıştırmak için crates.io'da kitaplıklar bulabilirsiniz :

  • docopt : sadece yardım mesajını yazarsınız ve ayrıştırma kodu sizin için oluşturulur.
  • clap : akıcı bir API kullanarak ayrıştırmak istediğiniz seçenekleri açıklarsınız. Dokümana göre daha hızlı ve daha fazla kontrol sağlar.
  • getopts : popüler C kütüphanesinin limanı. Daha düşük seviye ve daha fazla kontrol.
  • structopt : alkış üzerine inşa edilmiş, kullanımı daha ergonomik.

2
Ayrıca pas 0.8 ile sadece kullanmalısınızprintln(args[0])
Leo Correa

6
Yukarıdaki yorumlar (@LeoCorrea / @ S4M tarafından) cevabın eski bir versiyonuna atıfta bulundu; cevabın mevcut sürümü en güncel bilgileri içerir.
Nickolay

22

Docopt , bir kullanım dizesinden sizin için ayrıştırıcı oluşturan Rust için de kullanılabilir. Rust'ta bir bonus olarak, yapıyı otomatik olarak oluşturmak ve tür tabanlı kod çözme yapmak için bir makro kullanılabilir:

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

Options:
    -a, --archive  Copy everything.
")

Ve args ile alabilirsiniz:

let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

README ve dokümantasyonda birçok tam çalışma örneği vardır.

Feragatname: Bu kütüphanenin yazarlarından biriyim.



10

Benim için getopts her zaman çok düşük seviye hissettim ve docopt.rs çok fazla sihirdi. İhtiyacım olursa hala tüm özellikleri sağlayan açık ve anlaşılır bir şey istiyorum.

Clap-r'lerin işe yaradığı yer burasıdır .
Python'dan biraz argparse gibi geliyor. İşte nasıl göründüğüne bir örnek:

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();

Parametrelerinize şu şekilde erişebilirsiniz:

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);

( Resmi belgelerden kopyalanmıştır )


1
Ben clap-rs bir yaml dosyasında arayüz tanımlamak sağlar gibi. Ayrıca, gerçekten hoş görünümlü kullanım ifadeleri üretir.
Chuck Wooters

Bu, CLI uygulamamı hızlı bir şekilde kurmama yardımcı oldu. Teşekkür ederim!
dimitarvp

4

0.8 / 0.9 sürümünden itibaren, işlev args () işlevine giden doğru yol ::std::os::args, yani:

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

Rust'un şu anda standart IO ile bile hala oldukça uçucu olduğu görülüyor, bu yüzden bu oldukça hızlı bir şekilde eski olabilir.


Güncelleme için teşekkürler! Sanırım 1.0 yayınlandıktan sonra kabul edilen cevabı tekrar gözden geçirmem gerekecek.
shutefan

3

Rust tekrar değişti. os::args()lehine itiraz edilmiştir std::args(). Ancak std::args()bir dizi değil, bir yineleyici döndürür . Komut satırı bağımsız değişkenleri üzerinden yineleme yapabilirsiniz, ancak bunlara aboneliklerle erişemezsiniz.

http://doc.rust-lang.org/std/env/fn.args.html

Komut satırı bağımsız değişkenlerini bir dizeler vektörü olarak istiyorsanız, şimdi çalışacaktır:

use std::env;
...
let args: Vec<String> = env::args().map(|s| s.into_string().unwrap()).collect();

Pas - değişimin acısını kucaklamayı öğrenin.


8
Şimdi sadece yapman gerekiyor env::args().collect().
tshepang

2

@barjak ne dedi dizeleri için çalışır, ancak bir sayı olarak argümana ihtiyacınız varsa (bu durumda bir uint) şöyle dönüştürmeniz gerekir:

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

2

Ayrıca structopt'a göz atın:

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


1

Daha yeni Rust sürümleri (Rust> 0.10 / 11) itibariyle dizi sözdizimi çalışmaz. Get yöntemini kullanmanız gerekir.

[Edit] Dizi sözdizimi (tekrar) gece çalışır. Böylece alıcı veya dizi dizini arasında seçim yapabilirsiniz.

use std::os;

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

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

Bu eski bir ifadedir. En son Rust geceleri Vecs üzerindeki indeksleme sözdizimini destekler . Sanırım bir ay kadar orada. Bu örneğe bakın .
Vladimir Matveev

1

Pas Şimdi biri ile komut satırı argümanları ayrıştırmak olurdu Mayıs 2013 den Calvin'in cevap beri gelişti 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);
}

Sadece kayıt için: as_slice()artık mevcut değil ve &argsbunun yerine kullanılmalıdır.
Slava Semushin

1

Pas kitabı "Hayır stdlib" bölüm kapakları nasıl komut satırları parametreleri (başka şekilde) erişmek için.

// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    0
}

Şimdi, örnek, #![no_std]normalde std kütüphanesinin ikili için gerçek giriş noktasına sahip olacağı ve denilen küresel bir işlevi çağıracağı anlamına geldiğini düşündüğüm de var main(). Başka bir seçenek de ' mainşimi devre dışı bırakmak ' ile #![no_main]. Hangi yanılmıyorsam derleyiciye programınızın nasıl başlatıldığı konusunda tam kontrol sahibi olduğunuzu söylüyor.

#![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
}

Tek yapmanız gereken komut satırı argümanlarını okumaksa, bunun bir şeyler yapmanın 'iyi' bir yolu olduğunu düşünmüyorum. std::osDiğer yanıtlar sözü modül şeyler yapmanın çok daha iyi bir yol olarak görünmektedir. Bu cevabı tamamlama uğruna gönderiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.