2013-03-25 127 views

回答

123

您可以通過使用std::env::argsstd::env::args_os函數來訪問命令行參數。這兩個函數都會在參數上返回一個迭代器。前者迭代String s(很容易處理),但如果其中一個參數不是有效的unicode,則會發生混亂。後者遍歷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]); 
    } 
} 

您可以使用整個standard iterator toolbox用這些參數來工作。例如,僅檢索的第一個參數:

use std::env; 

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

你可以找到關於crates.io庫用於解析命令行參數:

  • docopt:你剛纔寫的幫助信息,並生成解析代碼爲你。
  • clap:你描述了你想用流利的API解析的選項。比docopt更快,讓你更有把握。
  • getopts:流行的C庫的端口。更低層次,甚至更多的控制。
+2

還有鏽0.8你應該只使用'println(args [0])' – 2013-09-27 02:24:29

+4

上面的評論(@LeoCorrea/@ S4M)引用了老版本的答案;答案的當前版本包含最新的信息。 – Nickolay 2017-03-11 09:11:57

2

什麼@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") 
    } 
} 
10

鏽有getopt說明式的CLI參數解析在getopts module

+2

網址更改:http://doc.rust-lang.org/getopts/index.html – drhodes 2014-06-27 04:00:25

+1

儘管此鏈接可能會回答問題,但最好在此處包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/ review/low-quality-posts/17893179) – 2017-11-09 15:47:33

3

從版本0.8/0.9,在函數參數)的正確路徑(將::std::os::args,即:

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

看來,鏽病仍相當波動,現在甚至標準IO,所以這可能會很快過時。

+0

感謝您的更新!猜測1.0發佈後我將不得不重新考慮接受的答案。 – shutefan 2014-01-16 20:59:25

1

從較新的Rust版本(Rust> 0.10/11)開始,數組語法將不起作用。你將不得不使用get方法。

[編輯]數組語法在夜間工作(再次)。所以你可以在getter或array索引之間進行選擇。

use std::os; 

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

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

這是陳舊的陳述。最新的Rust nightlies支持'vec's的索引語法。我想它在那裏一個月左右。看[這個例子](http://is.gd/YRvx3C)。 – 2014-08-14 18:54:26

+0

語法快速移動,所以也許它再次改變...... – stormpat 2014-08-14 19:22:49

1

自從2013年5月加爾文回答以來,Rust已經發展。現在,人們會解析命令行參數與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); 
} 
+0

只是爲了記錄:'as_slice()'不再存在,應該使用'&args'來代替。 – 2016-10-13 19:15:37

18

Docopt也可用於除鏽,這從使用字符串生成一個解析器爲您服務。作爲防鏽獎金,宏可以用來自動生成結構,做類型的基於解碼:

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和documentation有充足完整的工作例子。

聲明:我是該庫的作者之一。

1

Rust book "No stdlib" chapter涵蓋了如何訪問命令行參數(另一種方式)。現在

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

,示例確實也有#![no_std]我認爲,通常,在std庫會對您的二進制的真正入口點和調用一個名爲main()全局函數的手段。另一種選擇是用#![no_main]'禁用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模塊似乎是一個更好的做事方式。爲了完成,我發佈了這個答案。

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 2015-02-23 02:11:34

6

對我來說,getopts總是覺得太低級,docopt.rs太神奇了。 我想要一些明確和直接的東西,如果我需要它們,仍然可以提供所有功能。

這就是clap-rs派上用場。
這感覺有點像從Python的argparse。 這裏是它的外觀像一個例子:

let matches = App::new("myapp") 
         .version("1.0") 
         .author("Kevin K. <[email protected]>") 
         .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

我喜歡clap-rs讓你在yaml文件中定義你的接口。此外,它產生了非常漂亮的使用語句。 – 2017-02-19 20:43:54

0

(從official documentation複製)還檢查了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); 
} 

https://github.com/TeXitoi/structopt