使用Rust开发命令行程序(下)(rust执行cmd命令)
前言
Rust 的标准库虽然强大,但对于一些复杂功能来说,使用第三方库可以显著提高开发效率。在命令行程序开发中,clap 和 structopt 是两款广泛使用的库,它们能够帮助我们快速实现参数解析和命令管理。本章将详细介绍如何使用这两个库来构建强大的命令行程序。
引入第三方库
方式一
修改 Cargo.toml
在项目的 Cargo.toml 文件中添加依赖:
[package]
name = "command_line_demo"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.5.23", features = ["derive"] }
structopt = "0.3.26"
通过 cargo build 下载并构建依赖库。
方式二
直接使用cargo add命令直接添加依赖,具体如下所示:
cargo add clap --features derive
cargo add structopt
使用clap
clap(Command Line Argument Parser)是 Rust 中最流行的命令行参数解析库之一,它提供了简单直观的 API 和丰富的功能。
基本用法
示例:解析简单的参数
use clap::{Arg, Command};
fn main() {
let matchs = Command::new("My Cli App") // 创建一个Command结构体实例
.version("0.1.0") // 版本信息
.author("Alen") // 作者信息
.about("Does awesome things") // 命令行简介
.arg( // arg是一个宏,从字符串用法中创建Arg
Arg::new("name") // 创建一个Arg实例,必须传入一个唯一的参数名称
.short('n') // 参数短名称
.long("name") // 参数m长名称
.value_name("NAME") // 帮助消息/用法中参数值的占位符。
.help("Sets a custom name") // 参数帮助信息
.required(true) // 参数是否必须
)
.arg(
Arg::new("debug")
.short('d')
.long("debug")
.help("Sets a custom debug flag")
)
.get_matches(); // 解析env::args_os ,失败时退出。
if let Some(name) = matchs.get_one::<String>("name") {
println!("Hello {:?}", name);
}
// get_one: 获取特定选项或位置参数的值。
// 即在运行时获取附加值的参数。如果使用了错误的类型,则返回错误。
// 如果该选项不存在,则返回None 。
if let Some(debug) = matchs.get_one::<String>("debug") {
println!("Debug: {:?}", debug);
}
}
运行结果如下所示:
command_line_demo git:(master) cargo run -- --name alen --debug true
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/command_line_demo --name alen --debug true`
Hello "alen"
Debug: "true"
使用 derive 特性
clap 提供了 derive 宏,可以用结构体定义命令行参数,更加简洁。
示例:
use clap::Parser;
#[derive(Debug, Parser)] // 在宏里面定义命令行相关的信息
#[command(version = "0.0.1", author = "Alen", about="a command lint tools.")]
struct Cli {
#[arg(short, long)] // 参数的长短
name: String,
#[arg(short, long, default_value = "1")] // 参数的默认值等
count: u8,
}
fn main() {
let args = Cli::parse(); // 使用了Parser自动帮Cli这个结构体实现了一些triat
for _ in 0..args.count {
println!("{}", args.name);
}
}
注意:使用宏特性编写命令行程序,在添加依赖时需要增加derive这个特性
运行效果如下所示:
command_line_demo git:(master) cargo run -- --name alen --count 2
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
Running `target/debug/command_line_demo --name alen --count 2`
alen
alen
command_line_demo git:(master)
使用 structopt
structopt 是一个基于 clap 的库,提供类似 derive 的功能。它是早期版本的简化方案,功能已逐渐被 clap 的 derive 特性替代,但仍在一些项目中被使用。
基本用法
示例:
use structopt::StructOpt;
#[derive(Debug, StructOpt)] // 在结构体上面使用StructOpt使得Cli拥有了某种trait
#[structopt(name="My Cli app", about="a command lint tools")] // 在宏里面定义命令行相关的信息
struct Cli {
#[structopt(short, long)]
name: String,
#[structopt(short, long)]
debug: bool,
}
fn main() {
let args = Cli::from_args(); // 解析命令行
println!("{:?}", args.name);
if args.debug {
println!("{:#?}", args.debug);
}
}
运行效果如下所示:
command_line_demo git:(master) cargo run -- --name alen --debug
Compiling command_line_demo v0.1.0 (/Users/Alen/Workspaces/Rust/command_line_demo)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.80s
Running `target/debug/command_line_demo --name alen --debug`
"alen"
true
创建命令行工具的种类
单命令工具
适用于功能简单的工具,所有参数都作用于一个命令。
多子命令工具
适用于功能复杂的工具,每个子命令代表一个功能。
小结
clap 的优势:
- 功能强大且灵活,支持多种方式定义参数(手动、derive 宏)。
- 适合复杂命令行工具的开发。
structopt 的特点:
- 简洁优雅,但功能已经被 clap 的 derive 取代。
选择标准:
- 如果需要最新功能,建议使用 clap。
- 如果项目已有 structopt,可以继续使用或迁移到 clap
通过本章的学习,你已经掌握了使用第三方库 clap 和 structopt 创建功能丰富的命令行工具的能力。在下一章中,我们将结合实际项目,把这些知识应用于开发一个完整的命令行程序。