สนิมกวดวิชาไม่ได้อธิบายวิธีการใช้พารามิเตอร์จากบรรทัดคำสั่ง fn main()
จะแสดงเฉพาะกับรายการพารามิเตอร์ที่ว่างเปล่าในตัวอย่างทั้งหมด
วิธีที่ถูกต้องในการเข้าถึงพารามิเตอร์บรรทัดคำสั่งmain
คืออะไร?
สนิมกวดวิชาไม่ได้อธิบายวิธีการใช้พารามิเตอร์จากบรรทัดคำสั่ง fn main()
จะแสดงเฉพาะกับรายการพารามิเตอร์ที่ว่างเปล่าในตัวอย่างทั้งหมด
วิธีที่ถูกต้องในการเข้าถึงพารามิเตอร์บรรทัดคำสั่งmain
คืออะไร?
คำตอบ:
คุณสามารถเข้าถึงอาร์กิวเมนต์บรรทัดคำสั่งโดยใช้std::env::args
หรือstd::env::args_os
ฟังก์ชั่น ทั้งสองฟังก์ชั่นส่งคืน iterator มากกว่าข้อโต้แย้ง อดีต iterates กว่าString
s (ที่ง่ายต่อการทำงานด้วย) แต่ตกใจถ้าหนึ่งในข้อโต้แย้งไม่ถูกต้องยูนิโค้ด หลังซ้ำกว่าOsString
s และไม่ต้องตกใจ
โปรดทราบว่าองค์ประกอบแรกของตัววนซ้ำเป็นชื่อของโปรแกรมเอง (นี่เป็นข้อตกลงในระบบปฏิบัติการหลักทั้งหมด) ดังนั้นอาร์กิวเมนต์แรกจึงเป็นองค์ประกอบที่วนซ้ำแล้วครั้งที่สอง
วิธีง่ายๆในการจัดการกับผลลัพธ์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ยังมีให้สำหรับ Rust ซึ่งสร้าง parser ให้คุณจากสตริงการใช้งาน เป็นโบนัสใน Rust สามารถใช้แมโครเพื่อสร้าง struct และทำการถอดรหัสตามประเภทโดยอัตโนมัติ:
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 และเอกสารประกอบมีตัวอย่างการทำงานมากมาย
คำเตือน: ฉันเป็นหนึ่งในผู้เขียนของห้องสมุดนี้
สนิมมีgetopt
สไตล์การแยกอาร์กิวเมนต์ CLI ในgetopts ลัง
สำหรับฉัน getopts มักจะรู้สึกในระดับต่ำเกินไปและ docopt.rs เป็นเวทย์มนตร์มากเกินไป ฉันต้องการบางสิ่งที่ชัดเจนและตรงไปตรงมาซึ่งยังคงมีคุณสมบัติทั้งหมดหากฉันต้องการ
นี่คือที่clap-rs เข้ามามีประโยชน์
รู้สึกเหมือนขัดแย้งจาก Python นี่คือตัวอย่างของลักษณะที่ปรากฏ:
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);
(คัดลอกมาจากเอกสารอย่างเป็นทางการ )
ตั้งแต่เวอร์ชัน 0.8 / 0.9 เส้นทางที่ถูกต้องไปยังฟังก์ชัน args () จะเป็น::std::os::args
เช่น:
fn main() {
let args: ~[~str] = ::std::os::args();
println(args[0]);
}
ดูเหมือนว่าสนิมยังคงมีความผันผวนอยู่ในขณะนี้ด้วยมาตรฐาน IO ดังนั้นนี่อาจล้าสมัยไปอย่างรวดเร็ว
สนิมเปลี่ยนไปอีกครั้ง จะเลิกในความโปรดปรานของos::args()
std::args()
แต่std::args()
ไม่ได้เป็นอาร์เรย์จะส่งกลับiterator คุณสามารถวนซ้ำอาร์กิวเมนต์บรรทัดคำสั่ง แต่ไม่สามารถเข้าถึงได้ด้วยตัวห้อย
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();
สนิม - เรียนรู้ที่จะยอมรับความเจ็บปวดจากการเปลี่ยนแปลง
env::args().collect()
ตอนนี้คุณต้องทำเท่านั้น
สิ่งที่ @ 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")
}
}
ตรวจสอบโครงสร้างเช่นกัน:
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);
}
ในฐานะที่เป็นรุ่น Rust ใหม่ (สนิม> 0.10 / 11) ไวยากรณ์อาร์เรย์จะไม่ทำงาน คุณจะต้องใช้วิธีการรับ
[แก้ไข] ไวยากรณ์ของอาร์เรย์ทำงานได้อีกครั้งในตอนกลางคืน ดังนั้นคุณสามารถเลือกระหว่าง getter หรือ index array
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 ฉันคิดว่ามันอยู่ที่นั่นประมาณหนึ่งเดือน ดูตัวอย่างนี้
Rust ได้พัฒนาขึ้นตั้งแต่คำตอบของ Calvin ตั้งแต่เดือนพฤษภาคม 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
ควรใช้แทน
บทRust หนังสือ "No 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
โมดูลที่กล่าวถึงในคำตอบอื่น ๆ น่าจะเป็นวิธีที่ดีมากในการทำสิ่ง ฉันโพสต์คำตอบนี้เพื่อประโยชน์ของความสำเร็จ
println(args[0])