Các Rust hướng dẫn không giải thích làm thế nào để lấy thông số từ dòng lệnh. fn main()
chỉ được hiển thị với một danh sách tham số trống trong tất cả các ví dụ.
Cách chính xác để truy cập các tham số dòng lệnh từ là main
gì?
Các Rust hướng dẫn không giải thích làm thế nào để lấy thông số từ dòng lệnh. fn main()
chỉ được hiển thị với một danh sách tham số trống trong tất cả các ví dụ.
Cách chính xác để truy cập các tham số dòng lệnh từ là main
gì?
Câu trả lời:
Bạn có thể truy cập các đối số dòng lệnh bằng cách sử dụng std::env::args
hoặc các std::env::args_os
hàm. Cả hai hàm trả về một iterator qua các đối số. Các cựu lặp lại trên String
s (dễ làm việc với) nhưng hoảng loạn nếu một trong các đối số không phải là unicode hợp lệ. Cái sau lặp đi lặp lại trên OsString
s và không bao giờ hoảng loạn.
Lưu ý rằng phần tử đầu tiên của iterator là tên của chính chương trình (đây là quy ước trong tất cả các hệ điều hành chính), vì vậy đối số đầu tiên thực sự là phần tử lặp thứ hai.
Một cách dễ dàng để đối phó với kết quả args
là chuyển đổi nó thành Vec
:
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() > 1 {
println!("The first argument is {}", args[1]);
}
}
Bạn có thể sử dụng toàn bộ hộp công cụ iterator tiêu chuẩn để làm việc với các đối số này. Ví dụ: chỉ truy xuất đối số đầu tiên:
use std::env;
fn main() {
if let Some(arg1) = env::args().nth(1) {
println!("The first argument is {}", arg1);
}
}
Bạn có thể tìm thấy các thư viện trên crates.io để phân tích các đối số dòng lệnh:
Docopt cũng có sẵn cho Rust, công cụ tạo trình phân tích cú pháp cho bạn từ chuỗi sử dụng. Là một phần thưởng trong Rust, một macro có thể được sử dụng để tự động tạo cấu trúc và thực hiện giải mã dựa trên kiểu:
docopt!(Args, "
Usage: cp [-a] SOURCE DEST
cp [-a] SOURCE... DIR
Options:
-a, --archive Copy everything.
")
Và bạn có thể nhận được các đối số với:
let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
README và tài liệu có rất nhiều ví dụ hoạt động đầy đủ.
Tuyên bố miễn trừ trách nhiệm: Tôi là một trong những tác giả của thư viện này.
Rust có getopt
phân tích cú pháp đối số CLI kiểu mẫu trong thùng getopts .
Đối với tôi, getopts luôn cảm thấy quá thấp và docopt.rs là quá nhiều phép thuật. Tôi muốn một cái gì đó rõ ràng và đơn giản mà vẫn cung cấp tất cả các tính năng nếu tôi cần chúng.
Đây là nơi clap-rs có ích.
Nó cảm thấy giống như argparse từ Python. Đây là một ví dụ về cách nó trông như thế nào:
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();
Bạn có thể truy cập các tham số của mình như vậy:
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);
(Sao chép từ tài liệu chính thức )
Kể từ phiên bản 0.8 / 0.9, đường dẫn chính xác đến hàm args () sẽ là ::std::os::args
, nghĩa là:
fn main() {
let args: ~[~str] = ::std::os::args();
println(args[0]);
}
Có vẻ như Rust vẫn còn khá biến động ngay cả với IO tiêu chuẩn, do đó, điều này có thể trở nên lỗi thời khá nhanh.
Rust lại thay đổi. os::args()
được phản đối ủng hộ std::args()
. Nhưng std::args()
không phải là một mảng, nó trả về một iterator . Bạn có thể lặp lại các đối số dòng lệnh, nhưng không thể truy cập chúng bằng các mục con.
http://doc.rust-lang.org/std/env/fn.args.html
Nếu bạn muốn các đối số dòng lệnh là một vectơ của chuỗi, điều này sẽ hoạt động ngay bây giờ:
use std::env;
...
let args: Vec<String> = env::args().map(|s| s.into_string().unwrap()).collect();
Rust - học cách nắm lấy nỗi đau của sự thay đổi.
env::args().collect()
.
what @barjak nói hoạt động cho các chuỗi, nhưng nếu bạn cần đối số dưới dạng số (trong trường hợp này là một uint), bạn cần chuyển đổi như thế này:
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")
}
}
Ngoài ra kiểm tra 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);
}
Kể từ phiên bản Rust mới hơn (Rust> 0.10 / 11), cú pháp mảng sẽ không hoạt động. Bạn sẽ sử dụng phương thức get.
[Chỉnh sửa] Cú pháp mảng hoạt động (một lần nữa) hàng đêm. Vì vậy, bạn có thể chọn giữa chỉ số getter hoặc mảng.
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. Tôi đoán nó ở đó trong khoảng một tháng. Xem ví dụ này .
Rust đã phát triển kể từ câu trả lời của Calvin từ tháng 5 năm 2013. Bây giờ người ta sẽ phân tích các đối số dòng lệnh bằng 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()
không tồn tại nữa và &args
nên được sử dụng thay thế.
Chương "Cuốn sách không có stdlib" của Rust bao gồm cách truy cập các tham số dòng lệnh (một cách khác).
// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
Bây giờ, ví dụ này cũng có #![no_std]
cái mà tôi nghĩ có nghĩa là thông thường, thư viện std sẽ có điểm nhập thực sự cho nhị phân của bạn và gọi một hàm toàn cục được gọi main()
. Một tùy chọn khác là 'vô hiệu hóa main
shim' với #![no_main]
. Nếu tôi không nhầm thì nói với trình biên dịch rằng bạn đang kiểm soát hoàn toàn chương trình của bạn được bắt đầu như thế nào.
#![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
}
Tôi không nghĩ rằng đây là một cách làm 'tốt' nếu tất cả những gì bạn muốn làm là đọc các đối số dòng lệnh. Các std::os
mô-đun được đề cập trong các câu trả lời khác dường như là một cách tốt hơn để làm việc. Tôi đăng câu trả lời này vì mục đích hoàn thành.
println(args[0])