कमांड लाइन मापदंडों का उपयोग कैसे करें?


153

जंग ट्यूटोरियल कमांड लाइन से मानकों को लेने के लिए कैसे की व्याख्या नहीं करता। fn main()केवल सभी उदाहरणों में एक खाली पैरामीटर सूची के साथ दिखाया गया है।

कमांड लाइन मापदंडों तक पहुँचने का सही तरीका क्या है main?

जवाबों:


168

आप कमांड लाइन तर्कों का उपयोग std::env::argsया std::env::args_osकार्यों का उपयोग करके कर सकते हैं। दोनों कार्य तर्कों पर एक पुनरावृत्तिक लौटाते हैं। पूर्व Stringतर्क एस (कि काम करना आसान है) पर पैनिक करता है, लेकिन तर्कों में से कोई एक मान्य यूनिकोड नहीं है। उत्तरार्द्ध OsStringएस और कभी दहशत से अधिक पुनरावृत्तियों ।

ध्यान दें कि इट्रेटर का पहला तत्व प्रोग्राम का नाम है (यह सभी प्रमुख ओएस में एक सम्मेलन है), इसलिए पहला तर्क वास्तव में दूसरा पुनरावृत्त तत्व है।

इसके परिणाम से निपटने का एक आसान तरीका argsहै Vec:

use std::env;

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

आप इन तर्कों के साथ काम करने के लिए पूरे मानक iterator टूलबॉक्स का उपयोग कर सकते हैं । उदाहरण के लिए, केवल पहला तर्क प्राप्त करने के लिए:

use std::env;

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

आप कमांड लाइन तर्क को पार्स करने के लिए crates.io पर लाइब्रेरी पा सकते हैं :

  • docopt : आप केवल सहायता संदेश लिखते हैं, और आपके लिए पार्सिंग कोड उत्पन्न होता है।
  • ताली : आप उन विकल्पों का वर्णन करते हैं जिन्हें आप धाराप्रवाह एपीआई का उपयोग करके पार्स करना चाहते हैं। डॉकटॉप की तुलना में तेज़ और आपको अधिक नियंत्रण देता है।
  • getopts : लोकप्रिय सी लाइब्रेरी का पोर्ट। निम्न-स्तर और इससे भी अधिक नियंत्रण।
  • स्ट्रैचअप : ताली के ऊपर बनाया गया, यह उपयोग करने के लिए और भी अधिक एर्गोनोमिक है।

2
इसके अलावा जंग 0.8 के साथ आप बस का उपयोग करना चाहिएprintln(args[0])
सिंह Correa

6
उपरोक्त टिप्पणियां (@LeoCorrea / @ S4M द्वारा) उत्तर के एक पुराने संस्करण को संदर्भित करती हैं; उत्तर के वर्तमान संस्करण में अद्यतित जानकारी है।
निकोले

22

डस्टॉप रस्ट के लिए भी उपलब्ध है, जो आपके लिए उपयोग स्ट्रिंग से एक पार्सर उत्पन्न करता है। जंग में एक बोनस के रूप में, मैक्रो का उपयोग स्वचालित रूप से संरचना उत्पन्न करने और प्रकार आधारित डिकोडिंग करने के लिए किया जा सकता है:

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 और दस्तावेज़ीकरण में पूर्ण कार्य उदाहरण के बहुत सारे हैं।

अस्वीकरण: मैं इस पुस्तकालय के लेखकों में से एक हूं।



10

मेरे लिए, गेटटॉप्स को हमेशा बहुत कम-स्तरीय महसूस हुआ और docopt.rs बहुत अधिक जादू था। मैं कुछ स्पष्ट और सरल चाहता हूं जो अभी भी सभी सुविधाओं को प्रदान करता है यदि मुझे उनकी आवश्यकता है।

यह वह जगह है जहाँ क्लैप-आरएस काम में आता है।
यह पाइथन से होने वाले एक छोटे से विवाद जैसा लगता है। यहाँ एक उदाहरण दिया गया है कि यह कैसा दिखता है:

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

( आधिकारिक दस्तावेज से कॉपी किया गया )


1
मुझे यह पसंद है कि क्लैप-आरएस आपको एक यम फ़ाइल में अपने इंटरफ़ेस को परिभाषित करने देता है। इसके अलावा, यह वास्तव में अच्छी लग रही उपयोग बयान पैदा करता है।
चक वूटर्स

इससे मुझे जल्दी से अपना सीएलआई ऐप सेट करने में मदद मिली। धन्यवाद!
dimitarvp

4

संस्करण 0.8 / 0.9 के रूप में, फ़ंक्शन args () के लिए सही रास्ता होगा ::std::os::args, अर्थात:

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

ऐसा लगता है कि रस्ट अभी भी मानक आईओ के साथ अभी भी बहुत अस्थिर है, इसलिए यह काफी जल्दी से पुराना हो सकता है।


अद्यतन के लिए धन्यवाद! अनुमान है कि 1.0 जारी होने के बाद मुझे स्वीकार किए गए उत्तर पर पुनर्विचार करना होगा।
20

3

जंग फिर से बदल गई। 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();

जंग - परिवर्तन के दर्द को गले लगाना सीखो।


8
अब आपको केवल करने की आवश्यकता है env::args().collect()
tshepang

2

@barjak ने जो कहा वह स्ट्रिंग्स के लिए काम करता है, लेकिन अगर आपको एक नंबर के रूप में तर्क की आवश्यकता है (इस मामले में एक प्रकार का वृक्ष) तो आपको इस तरह बदलने की आवश्यकता है:

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

इसके अलावा संरचना को देखें:

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

नए जंग संस्करणों के रूप में (जंग> 0.10 / 11) सरणी सिंटैक्स अभ्यस्त काम करते हैं। तुम हो जाओ विधि का उपयोग करना होगा।

[संपादित करें] सरणी सिंटैक्स रात में (फिर से) काम करता है। तो आप गेट्टर या एरे इंडेक्स के बीच चयन कर सकते हैं।

use std::os;

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

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

यह अप्रचलित कथन है। नवीनतम रस्ट नाइटलाइट्स Vecएस पर सिंटेक्स सिंटैक्स का समर्थन करते हैं । मुझे लगता है कि यह एक महीने के लिए वहाँ है। इस उदाहरण को देखें ।
व्लादिमीर मतावेव

1

मई 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इसके बजाय इसका उपयोग किया जाना चाहिए।
स्लाव सेमुशिन

1

जंग पुस्तक "नहीं stdlib" अध्याय कवर कैसे कमांड लाइन पैरामीटर (एक और तरीका है) तक पहुँचने के लिए।

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

अब, उदाहरण में वह भी है #![no_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मॉड्यूल अन्य उत्तर में उल्लेख किया है काम करने के एक बेहतर तरीका हो रहा है। मैं इस जवाब को पूरा करने के लिए पोस्ट करता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.