163

Rustチュートリアルでは、コマンドラインからパラメーターを取得する方法については説明していません。fn main()すべての例で、空のパラメータリストでのみ表示されます。

からコマンドラインパラメータにアクセスする正しい方法は何mainですか?

4

12 に答える 12

183

std::env::argsまたはstd::env::args_os関数を使用して、コマンドライン引数にアクセスできます。どちらの関数も、引数に対してイテレータを返します。String前者はs(操作が簡単)を繰り返しますが、引数の1つが有効なUnicodeでない場合はパニックになります。後者はsを繰り返し、OsStringパニックになることはありません。

イテレータの最初の要素はプログラム自体の名前であることに注意してください(これはすべての主要なOSでの規則です)。したがって、最初の引数は実際には2番目の反復要素です。

の結果を処理する簡単な方法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:ヘルプメッセージを書くだけで、解析コードが生成されます。
  • clap:流暢なAPIを使用して解析するオプションを記述します。docoptよりも高速で、より詳細に制御できます。
  • getopts:人気のあるCライブラリのポート。低レベルでさらに多くの制御。
  • structopt:拍手の上に構築されているため、人間工学的に使用できます。
于 2013-03-25T18:16:47.837 に答える
24

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とドキュメントには、完全に機能する例がたくさんあります。

免責事項:私はこのライブラリの作成者の1人です。

于 2014-10-23T02:22:00.343 に答える
13

Rustには、 getoptsクレートgetoptでのスタイルのCLI引数解析があります。

于 2013-07-08T21:24:13.300 に答える
10

私にとって、getoptsは常に低レベルであると感じ、docopt.rsはあまりにも魔法でした。必要に応じてすべての機能を提供する、明示的でわかりやすいものが必要です。

ここでclap-rsが役に立ちます。
Pythonのargparseのように感じます。これがどのように見えるかの例です:

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

(公式ドキュメントからコピー)

于 2016-01-09T12:33:05.827 に答える
4

バージョン0.8/0.9の時点では、関数args()への正しいパスは次のようになります::std::os::args

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

Rustは現在、標準のI / Oでさえかなり不安定であるように思われるので、これはかなり早く時代遅れになる可能性があります。

于 2013-12-05T21:46:44.997 に答える
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();

さび-変化の痛みを受け入れることを学ぶ。

于 2015-02-05T23:47:53.970 に答える
3

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

于 2017-10-09T14:30:34.420 に答える
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")
    }
}
于 2013-05-11T17:46:01.480 に答える
1

新しい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
于 2014-08-11T17:19:08.017 に答える
1

Rustは、2013年5月のCalvinの回答以来進化してきました。これで、コマンドライン引数を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);
}
于 2014-10-17T13:36:21.363 に答える
1

Rustブックの「Nostdlib」の章では、コマンドラインパラメータにアクセスする方法(別の方法)について説明しています。

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

さて、この例には#![no_std]、通常、stdライブラリがバイナリの真のエントリポイントを持ち、と呼ばれるグローバル関数を呼び出すことを意味すると思いますmain()。もう1つのオプションは、「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回答で言及されているモジュールは、物事を行うためのはるかに優れた方法のようです。完成のためにこの回答を投稿します。

于 2014-11-10T14:43:23.117 に答える
0

コマンドライン引数を繰り返し処理する場合:

use std::env::{args,Args};

fn main() {
    let mut args:Args=args();
    // args.nth(0) cannot borrow as mutable. that is why  let mut args
    // nth return an element of iterator
    let first=args.nth(1).unwrap();
    // iterator has next method. we want to get the first element of next iterator. NOT args.nth(2)
    // chars returns an iterator
    let operator=args.nth(0).unwrap().chars().next().unwrap();
    let second=args.nth(0).unwrap();
}

n番目の引数に直接アクセスする場合:

fn get_nth_arg(n:usize)->String{
    std::env::args().nth(n).unwrap()
}
于 2022-02-24T23:14:55.307 に答える