關(guān)于Rust命令行參數(shù)解析以minigrep為例
一、新建項(xiàng)目
和往常一樣,我們先用 cargo new minigrep
創(chuàng)建一個(gè)新的二進(jìn)制項(xiàng)目:
$ cargo new minigrep $ cd minigrep
Cargo 自動(dòng)幫我們生成了一個(gè)基礎(chǔ)的 src/main.rs
文件,里面有一個(gè)簡(jiǎn)單的 “Hello, world!” 示例。我們會(huì)在此文件中編寫命令行解析的邏輯。
二、獲取命令行參數(shù)
要想在 Rust 中讀取命令行參數(shù),可以使用標(biāo)準(zhǔn)庫(kù)的 std::env::args
函數(shù)。
此函數(shù)會(huì)返回一個(gè)迭代器(iterator),包含程序啟動(dòng)時(shí)傳遞給它的所有命令行參數(shù)。
以下為一個(gè)最簡(jiǎn)單的示例(src/main.rs
):
use std::env; fn main() { let args: Vec<String> = env::args().collect(); println!("{:?}", args); }
我們?cè)谏厦孀隽藥准拢?/p>
use std::env;
:將std::env
模塊引入當(dāng)前作用域,以便使用env::args
。env::args()
:此函數(shù)返回一個(gè)迭代器,能夠依次提供命令行參數(shù)。collect()
:把迭代器轉(zhuǎn)換為一個(gè)包含所有參數(shù)的Vec<String>
。println!("{:?}", args);
:采用調(diào)試模式打印整個(gè)向量,驗(yàn)證它的內(nèi)容。
運(yùn)行結(jié)果演示
我們先不傳參數(shù)來看看默認(rèn)輸出:
$ cargo run Compiling minigrep v0.1.0 (~/minigrep) Finished dev [unoptimized + debuginfo] target(s) in 0.37s Running `target/debug/minigrep` ["target/debug/minigrep"]
可以看到,向量的第一個(gè)元素是可執(zhí)行文件的路徑或名稱(類似于 C 語(yǔ)言中的 argv[0]
)。
如果我們傳入兩個(gè)額外參數(shù)試試:
$ cargo run -- rust sample.txt ... ["target/debug/minigrep", "rust", "sample.txt"]
Rust 程序可獲取我們?cè)诿钚休斎氲?“rust
” 和 “sample.txt
” 兩個(gè)參數(shù)。
這里要注意 --
的用法:cargo run -- <args>
表示 --
后面的內(nèi)容是傳給編譯出來的程序本身,而非 cargo run
命令的參數(shù)。
三、將參數(shù)存入變量
打印出所有參數(shù)后,我們往往只關(guān)心其中的部分信息。比如在“minigrep”工具里,我們希望接收兩個(gè)參數(shù):
- 查詢字符串(query):要搜索的單詞或模式;
- 文件名(file_path):要在其中搜索的文件。
那么就可以在 main
函數(shù)中把參數(shù)按順序賦給變量。
示例代碼如下:
use std::env; fn main() { let args: Vec<String> = env::args().collect(); // args[0] 是程序本身 ("target/debug/minigrep") let query = &args[1]; // 第一個(gè)實(shí)際參數(shù) let file_path = &args[2]; // 第二個(gè)實(shí)際參數(shù) println!("Searching for: {}", query); println!("In file: {}", file_path); }
運(yùn)行并驗(yàn)證
$ cargo run -- to-do-list tasks.txt Finished dev [unoptimized + debuginfo] target(s) in 0.24s Running `target/debug/minigrep to-do-list tasks.txt` Searching for: to-do-list In file: tasks.txt
可以看到,程序正確地抓取到 “to-do-list
” 和 “tasks.txt
”。接下來,我們就能利用這兩個(gè)變量為后續(xù)的文件處理和搜索邏輯作準(zhǔn)備。
提示:如果要支持包含 Unicode 無效字符的參數(shù),std::env::args
會(huì)在遇到無效 Unicode 時(shí)觸發(fā) panic!
。此時(shí),可使用 std::env::args_os
返回 OsString
,從而更好地兼容各平臺(tái)。但在一般使用場(chǎng)景下,args
足夠滿足需求。
四、下一步:處理文件和搜索邏輯
在實(shí)際項(xiàng)目中,拿到 query
和 file_path
兩個(gè)參數(shù)后,我們往往會(huì)繼續(xù)執(zhí)行下列操作:
- 讀取文件內(nèi)容:使用
std::fs::read_to_string
或者文件 IO 相關(guān) API。 - 搜索匹配項(xiàng):對(duì)文件內(nèi)容逐行(或整體)進(jìn)行查找,找出與
query
相匹配的部分。 - 輸出搜索結(jié)果:根據(jù)需要將匹配到的行打印出來,或統(tǒng)計(jì)匹配數(shù)量等等。
后續(xù)還應(yīng)考慮更加健壯的錯(cuò)誤處理方式,比如:
- 未提供足夠的命令行參數(shù)時(shí),給出友好的提示信息;
- 文件無法打開或讀取時(shí)如何提示并退出;
- 搜索字符串為空時(shí)是否給用戶警告等。
五、總結(jié)
Rust 標(biāo)準(zhǔn)庫(kù)為命令行參數(shù)處理提供了一個(gè)非常簡(jiǎn)潔的入口——std::env::args()
。借助迭代器和 collect()
,我們可以快速拿到一個(gè) Vec<String>
,隨后就能像操作數(shù)組一樣輕松讀取或處理參數(shù)。同時(shí),你也可以借助社區(qū) crates(如 clap、structopt 等)在復(fù)雜命令行解析場(chǎng)景下更快上手。
在本文示例中,我們初步實(shí)現(xiàn)了一個(gè)迷你“grep”程序的命令行參數(shù)獲?。核芙邮找粋€(gè)搜索關(guān)鍵字和一個(gè)文件名,后續(xù)我們還會(huì)進(jìn)一步完善其搜索功能、文件處理及錯(cuò)誤處理等邏輯。相信通過這個(gè)小練習(xí),你已經(jīng)了解并掌握了 Rust 如何在命令行工具中優(yōu)雅地處理參數(shù)輸入!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Rust開發(fā)WebAssembly在Html和Vue中的應(yīng)用小結(jié)(推薦)
這篇文章主要介紹了Rust開發(fā)WebAssembly在Html和Vue中的應(yīng)用,本文將帶領(lǐng)大家在普通html上和vue手腳架上都來運(yùn)行wasm的流程,需要的朋友可以參考下2022-08-08Rust在寫庫(kù)時(shí)實(shí)現(xiàn)緩存的操作方法
Moka是一個(gè)用于Rust的高性能緩存庫(kù),它提供了多種類型的緩存數(shù)據(jù)結(jié)構(gòu),包括哈希表、LRU(最近最少使用)緩存和?支持TTL(生存時(shí)間)緩存,這篇文章給大家介紹Rust在寫庫(kù)時(shí)實(shí)現(xiàn)緩存的相關(guān)知識(shí),感興趣的朋友一起看看吧2024-01-01解讀Rust的Rc<T>:實(shí)現(xiàn)多所有權(quán)的智能指針方式
Rc<T> 是 Rust 中用于多所有權(quán)的引用計(jì)數(shù)類型,通過增加引用計(jì)數(shù)來管理共享數(shù)據(jù),只有當(dāng)最后一個(gè)引用離開作用域時(shí),數(shù)據(jù)才會(huì)被釋放,Rc<T> 適用于單線程環(huán)境,并且只允許不可變共享數(shù)據(jù);需要可變共享時(shí)應(yīng)考慮使用 RefCell<T> 或其他解決方案2025-02-02如何使用rust實(shí)現(xiàn)簡(jiǎn)單的單鏈表
實(shí)現(xiàn)單鏈表在別的語(yǔ)言里面可能是一件簡(jiǎn)單的事情,單對(duì)于Rust來說,絕對(duì)不簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于如何使用rust實(shí)現(xiàn)簡(jiǎn)單的單鏈表的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03