命令行解析
问题
Rust 如何构建命令行工具?
答案
clap 是 Rust 最流行的命令行解析库,支持 derive 宏声明式定义。
derive API(推荐)
use clap::{Parser, Subcommand, ValueEnum};
/// 一个简单的 CLI 工具
#[derive(Parser)]
#[command(name = "mytool", version, about = "演示 CLI 工具")]
struct Cli {
/// 输入文件路径
#[arg(short, long)]
input: String,
/// 输出格式
#[arg(short, long, default_value = "json", value_enum)]
format: OutputFormat,
/// 详细输出
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(ValueEnum, Clone)]
enum OutputFormat {
Json,
Csv,
Table,
}
#[derive(Subcommand)]
enum Commands {
/// 初始化项目
Init {
#[arg(short, long)]
name: String,
},
/// 运行任务
Run {
/// 任务名
task: String,
},
}
fn main() {
let cli = Cli::parse();
match cli.verbose {
0 => println!("正常模式"),
1 => println!("详细模式"),
_ => println!("调试模式"),
}
if let Some(cmd) = cli.command {
match cmd {
Commands::Init { name } => println!("初始化: {}", name),
Commands::Run { task } => println!("运行: {}", task),
}
}
}
使用方式:
mytool --input data.txt --format csv -vv init --name myproject
常用特性
| 特性 | 属性 | 说明 |
|---|---|---|
| 必选参数 | 默认 | input: String |
| 可选参数 | Option<T> | input: Option<String> |
| 默认值 | default_value | #[arg(default_value = "8080")] |
| 环境变量 | env | #[arg(env = "PORT")] |
| 布尔开关 | action = SetTrue | --verbose |
| 计数 | action = Count | -vvv → 3 |
| 枚举值 | value_enum | 自动生成可选值列表 |
常见面试问题
Q1: clap 的 derive API 和 builder API 有什么区别?
答案:
- derive API:通过
#[derive(Parser)]声明式定义,代码简洁,编译时检查,推荐大多数场景 - builder API:
Command::new().arg(...)编程式构建,运行时动态构造参数,适合需要动态生成参数的场景
两者功能等价,derive API 是 builder API 的语法糖。