arg参数提示
cargo add clap -F derive
short短参数
- 可以使用
short='A'设置简短别名
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short)]name: String,// 需要使用单引号#[arg(short='A')]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -hUsage: test_clap -n <NAME> -A <AGE>Options:-n <NAME> -A <AGE> -h, --help Print help
long长参数
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long)]name: String,// 设置长参数别名#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -hUsage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> -A, --AGE-AAA <AGE> -h, --help Print help
设置别名
不可见别名
alias单个别名
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 别名设置#[arg(short, long, alias="VV1")]name: String,#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -h
Usage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> -A, --AGE-AAA <AGE> -h, --help Print help
aliases多个别名
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 别名设置#[arg(short, long, aliases=["V1", "V2"])]name: String,#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -h
Usage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> -A, --AGE-AAA <AGE> -h, --help Print help
可见别名
visible_alias单个别名
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 别名设置#[arg(short, long, visible_alias="VV1")]name: String,#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
Usage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> [alias: --VV1]-A, --AGE-AAA <AGE> -h, --help Print help
visible_aliases多个别名
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 别名设置#[arg(short, long, visible_aliases=["V1", "V2"])]name: String,#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
Usage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> [aliases: --V1, --V2]-A, --AGE-AAA <AGE> -h, --help Print help
设置value_name
设置填入参数的显示内容
use clap::Parser;
use std::path::PathBuf;#[derive(Parser, Debug)]
struct MyCli {// value_name设置#[arg(short, long, value_name="Name")]name: String,#[arg(short='A', long="AGE-AAA", value_name="Age")]age: String,// 文件类型也可以#[arg(short, long, value_name = "CONFIG.toml")]config: PathBuf,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
Usage: test_clap --name <Name> --AGE-AAA <Age> --config <CONFIG.toml>Options:-n, --name <Name> # 变为了value_name值-A, --AGE-AAA <Age> # 变为了value_name值-c, --config <CONFIG.toml> # 变为了value_name值-h, --help Print help
帮助排序display_order
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, display_order = 3)]name: String,#[arg(short, long, display_order = 1)]age: String,#[arg(short, long, display_order = 2)]debug: bool,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}-{}", cli.name, cli.age, cli.debug);
}
target/debug/test_clap -h
Usage: test_clap [OPTIONS] --name <NAME> --age <AGE>Options:-a, --age <AGE> # display_order=1-d, --debug # display_order=2-n, --name <NAME> # display_order=3-h, --help Print help
参数分组help_heading
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, help_heading = "用户信息")]name: String,#[arg(short, long, help_heading = "用户信息")]age: String,#[arg(short, long, help_heading = "测试")]debug: bool,
}fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
Usage: myapp [OPTIONS] --name <NAME> --age <AGE>Options:-h, --help Print help用户信息:-n, --name <NAME>-a, --age <AGE> 测试:-d, --debug
参数隐藏hide
设置
hide = true,命令行帮助不会显示,但是可以正常使用
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long)]name: String,#[arg(short, long)]age: String,#[arg(short, long, hide = true)]debug: bool,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}-{}", cli.name, cli.age, cli.debug);
}
Usage: test_clap --name <NAME> --age <AGE>Options:-n, --name <NAME> -a, --age <AGE> -h, --help Print help
设置help参数说明
使用斜杠说明
需要使用
///添加说明,-h/--help都使用一样的说明
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {/// 输入名字#[arg(short, long)]name: String,/// 输入/// 年龄// 上面的是说明,我这个是注释#[arg(short='A', long="AGE-AAA")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -hUsage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> 输入名字-A, --AGE-AAA <AGE> 输入 年龄-h, --help Print help
设置-h说明help
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, help="这是名字")]name: String,#[arg(short='A', long="AGE-AAA", help="这是年龄")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -hUsage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> 这是名字-A, --AGE-AAA <AGE> 这是年龄-h, --help Print help
设置--help说明long_help
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, help="这是名字", long_help="请输入你的名字")]name: String,#[arg(short='A', long="AGE-AAA", help="这是年龄", long_help="请输入你的年龄")]age: String,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
cargo run -- -hUsage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME> 这是名字-A, --AGE-AAA <AGE> 这是年龄-h, --help Print help (see more with '--help')
cargo run -- --helpUsage: test_clap --name <NAME> --AGE-AAA <AGE>Options:-n, --name <NAME>请输入你的名字-A, --AGE-AAA <AGE>请输入你的年龄-h, --helpPrint help (see a summary with '-h')
设置默认值
未输入选项
default_value运行检查
字符串字面量
- 接受 字符串字面量 (
&str) - 值在运行时通过
FromStr解析成目标类型 - 如果解析失败,运行时 panic(编译期不检查)
- 适用于需要动态字符串的场景(如从环境变量拼接)
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, default_value = "Tom")]name: String,#[arg(short, long, default_value = "32")]age: i32, // 字符串 "32" 在运行时解析成 i32
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age + 2);
}
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> [default: Tom]-a, --age <AGE> [default: 32]-h, --help Print help
default_value_t编译期检查
- 接受目标类型的直接值(age这里是
i32而不是&str) - 编译期类型检查,类型不匹配直接编译失败
- 更安全,IDE 能自动补全和类型推断
- 适用于静态常量场景
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 需要填写对应的类型#[arg(short, long, default_value_t = "Tom".to_string())]name: String,// 需要填写对应的类型#[arg(short, long, default_value_t = 32)]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age + 2);
}
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> [default: Tom]-a, --age <AGE> [default: 32]-h, --help Print help
输入选项没有输入值
default_missing_value运行检查
#[arg(short, long, default_value = "Tom", default_missing_value = "Tom1")]
name: String,
./app # default_value值Tom生效
./app --name # default_missing_value值Tom1生效
./app -name Bob # 设置值Bob生效
default_missing_value_t编译器检查
#[arg(short, long, default_value_t = 18, default_missing_value_t = 30)]
age: i32,
./app # default_value_t值18生效
./app --age # default_missing_value_t值30生效
./app --age 35 # 设置值35生效
隐藏默认值
hide_default_value
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 设置默认值隐藏hide_default_value=true#[arg(short, long, default_value_t = "Tom".to_string(), hide_default_value=true)]name: String,// 需要填写对应的类型#[arg(short, long, default_value_t = 32)]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age + 2);
}
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> -a, --age <AGE> [default: 32]-h, --help Print help
环境变设置默认值
env
clap需要开启env的features
- 优先级
| 场景 | 最终值 |
|---|---|
--age 30 |
30(命令行最高) |
MY_AGE=20 cargo run |
20(环境变量次之) |
cargo run |
20(默认值兜底) |
env配和default_value
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, default_value = "Tom", env = "MY_NAME")]name: String,#[arg(short, long, default_value = "20", env = "MY_AGE")]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> [env: MY_NAME=] [default: Tom]-a, --age <AGE> [env: MY_AGE=] [default: 20]-h, --help Print help
env配和default_value_t
default_value_t和env配合使用时,default_value_t的值类型必须与字段定义的类型一致。这是default_value_t的核心设计——编译期类型检查
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, default_value_t = "Tom".to_string(), env = "MY_NAME")]name: String,#[arg(short, long, default_value_t = 20, env = "MY_AGE")]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> [env: MY_NAME=] [default: Tom]-a, --age <AGE> [env: MY_AGE=11] [default: 20]-h, --help Print help
hide_env隐藏env字段提示
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short,long,default_value = "Tom",env = "MY_NAME",hide_env = true)]name: String,#[arg(short,long,default_value = "20",env = "MY_AGE",hide_env = true)]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
target/debug/test_clap -h
Usage: test_clap [OPTIONS]Options:-n, --name <NAME> [default: Tom]-a, --age <AGE> [default: 20]-h, --help Print help
hide_env_values隐藏环境变量值
hide_env_values用于隐藏环境变量的实际值,防止敏感信息(如密码、Token)泄露到帮助文档中
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {/// 普通配置,可以显示#[arg(long, env = "PORT", default_value_t = 8080)]port: u16,/// 敏感信息,隐藏值#[arg(long, env = "API_KEY", hide_env_values = true)]api_key: String,/// 也敏感,隐藏#[arg(long, env = "DB_PASSWORD", hide_env_values = true)]db_password: String,
}fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
PORT=3000 API_KEY=secret DB_PASSWORD=123 cargo run -- --helpUsage: test_clap [OPTIONS] --api-key <API_KEY> --db-password <DB_PASSWORD>Options:--port <PORT> 普通配置,可以显示 [env: PORT=3000] [default: 8080]--api-key <API_KEY> 敏感信息,隐藏值 [env: API_KEY]--db-password <DB_PASSWORD> 也敏感,隐藏 [env: DB_PASSWORD]-h, --help Print help
设置参数要求
必填参数required
如果
default_value_t存在,则required可以省略,因为默认值保证参数总有值
- 参数是否必须提供:不仅取决于
required,更取决于字段类型和是否有默认值。 - 真正可选的参数:请使用
Option<T>或添加default_value
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// name为必填参数#[arg(short, long, required = true)]name: String,// age也为必填参数#[arg(short, long)]age: i32,
}fn main() {let cli = MyCli::parse();println!("cli.name: {}-{}", cli.name, cli.age);
}
可选参数
使用Option<T> 类型
- 用户提供时,
age为Some(value);不提供时为None。 required自动被忽略(因为Option已经表示了可选性)。
#[arg(short, long)]
age: Option<i32>,
设置默认值
- 用户不提供时,
age取默认值。 - 使用
default_value_t或者default_value
#[arg(short, long, default_value_t = 18)]
age: i32,
枚举值(限定可选值)
// 需要导入ValueEnum
use clap::{Parser, ValueEnum};#[derive(Debug, Clone, ValueEnum)]
enum LogLevel {Debug,Info,Warn,Error,
}#[derive(Parser, Debug)]
struct MyCli {// 需要定义value_enum// 设置default_value_t默认值#[arg(short, long, value_enum, default_value_t = LogLevel::Info)]log: LogLevel
}fn main() {let cli = MyCli::parse();println!("cli.name: {:?}", cli.log);
}
Usage: test_clap [OPTIONS]Options:-l, --log <LOG> [default: info] [possible values: debug, info, warn, error]-h, --help Print help
多值参数
value_delimiter 单参数-多值
-i x,xx,xxx传值
分隔符
| 分隔符 | 问题 |
|---|---|
, |
通用,但如果值本身含逗号会冲突 |
: |
Unix 路径常用,安全 |
| |
shell 需要转义 |,麻烦 |
(空格) |
shell 会先把空格拆成多个参数,需要加引号 "a b c" |
#[arg(short, long, value_delimiter = ':')]
paths: Vec<String>,#[arg(short, long, value_delimiter = '|')]
items: Vec<String>,#[arg(short, long, value_delimiter = ' ')] // 空格也可以
words: Vec<String>,
案例
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// value_delimiter='设置分隔符'#[arg(short, long, value_delimiter=',')]item: Vec<String>
}fn main() {let cli = MyCli::parse();println!("cli.item: {:?}", cli.item);
}
target/debug/test_clap -i 1,2,3,4
cli.item: ["1", "2", "3", "4"]
num_args重复传参
item: Vec<String>自动开启了ArgAction::Append,所以可多次调用-inum_args控制
-i xx xx xx的参数个数
控制范围
#[arg(short, long, num_args = 1..)] // 传入1个获取多个
#[arg(short, long, num_args = 2..=4)] // 必须传 2 到 4 个
#[arg(short, long, num_args = 0..=3)] // 最多 3 个
#[arg(short, long, num_args = 3)] // 必须恰好 3 个
案例
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// num_args设置-i中需要填写多少个参数的个数#[arg(short, long, num_args=3)]item: Vec<String>
}fn main() {let cli = MyCli::parse();println!("cli.item: {:?}", cli.item);
}
Usage: test_clap [OPTIONS]Options:-i, --item <ITEM> <ITEM> <ITEM> -h, --help Print help
target/debug/test_clap -i 1 2 3 # num_args=3表示必须传入3个值
cli.item: ["1", "2", "3"]
允许负数值
clap::ArgAction
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, allow_hyphen_values = true)]offset: i32,
}fn main() {let cli = MyCli::parse();println!("cli.offset: {}", cli.offset);
}
target/debug/test_clap -o -30
cli.offset: -30
设置clap::ArgAction
action设置的是"用户传参时,值怎么变":Set是直接赋值,SetTrue是变 true,Count是累加,Append是追加到列表。它决定了命令行参数到 Rust 字段的映射规则
Count计数参数(-vvv)
作用是用同一个 flag 的重复次数来控制级别/程度,常见于控制日志详细程度。
案例
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {/// 详细程度(-v, -vv, -vvv)// 设置action为clap::ArgAction::Count#[arg(short, long, action = clap::ArgAction::Count)]verbose: u8,
}fn main() {let cli = MyCli::parse();// cli.verbose返回次数match cli.verbose {0 => println!("只显示错误"),1 => println!("显示警告 + 错误"),2 => println!("显示信息 + 警告 + 错误"),3 => println!("显示调试信息"),_ => println!("全部调试(包括 trace)"),}
}
cargo run -- # verbose = 0,只显示错误
cargo run -- -v # verbose = 1,显示警告
cargo run -- -vv # verbose = 2,显示信息
cargo run -- -vvv # verbose = 3,显示调试
cargo run -- -vvvv # verbose = 4,全部
场景使用
use clap::Parser;
use tracing::Level;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, action = clap::ArgAction::Count)]verbose: u8,
}fn main() {let cli = MyCli::parse();// 控制日志显示级别let level = match cli.verbose {0 => Level::ERROR,1 => Level::WARN,2 => Level::INFO,3 => Level::DEBUG,_ => Level::TRACE,};tracing_subscriber::fmt().with_max_level(level).init();tracing::info!("应用启动");
}
Set默认值
默认值, 允许出现一次
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, action=clap::ArgAction::Set)]name: String
}fn main() {let cli = MyCli::parse();println!("cli.name: {:?}", cli.name);
}
target/debug/test_clap --name Tom
cli.name: "Tom"# 错误
# target/debug/test_clap --name Tom --name Bob
# target/debug/test_clap --name Tom Bob
Append显式追加到 Vec
可以多次出现
-i调用
// 默认开启了action = clap::ArgAction::Append
#[arg(short, long)]
files: Vec<String>,
基础使用
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// num_args设置-i参数个数#[arg(short, long, action=clap::ArgAction::Append)]item: Vec<String>
}fn main() {let cli = MyCli::parse();println!("cli.item: {:?}", cli.item);
}
Usage: test_clap [OPTIONS]Options:-i, --item <ITEM> -h, --help Print help
target/debug/test_clap -i 1 -i 22 -i 33
cli.item: ["1", "22", "33"]
结合num_args
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// num_args设置-i参数个数#[arg(short, long, action=clap::ArgAction::Append, num_args = 2)]item: Vec<String>
}fn main() {let cli = MyCli::parse();println!("cli.item: {:?}", cli.item);
}
Usage: test_clap [OPTIONS]Options:-i, --item <ITEM> <ITEM> -h, --help Print help
target/debug/test_clap -i 1 2 -i 3 4
cli.item: ["1", "2", "3", "4"]
布尔值设置
默认SetTrue
默认值是
false,--is_test激活了才是true
action=clap::ArgAction::SetTrue
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// 默认是action=clap::ArgAction::SetTrue模式#[arg(short, long)]is_test: bool
}fn main() {let cli = MyCli::parse();println!("cli.is_test: {:?}", cli.is_test);
}
# 默认false值
target/debug/test_clap
cli.is_test: false# 输入后才是true
target/debug/test_clap --is-test
cli.is_test: true
相反设置SetFalse
效果不输入时
true,输入后变为false
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, action=clap::ArgAction::SetFalse)]skip: bool
}fn main() {let cli = MyCli::parse();println!("cli.skip: {:?}", cli.skip);
}
# 默认true值
target/debug/test_clap
cli.skip: true# 输入后变为false
target/debug/test_clap --skip`
cli.skip: false
参数关系
参数依赖requires
设置单个依赖
使用
-p、--password时,必须传入-u、--username
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long)]username: String,/// 必须和 --username 一起使用#[arg(short, long, requires = "username")]password: String,
}fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
Usage: test_clap --username <USERNAME> --password <PASSWORD>Options:-u, --username <USERNAME> -p, --password <PASSWORD> 必须和 --username 一起使用-h, --help Print help
设置多个依赖
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long)]username: Option<String>,#[arg(short, long)]password: Option<String>,/// 必须和 --username/--password 一起使用#[arg(short, long, requires = "username", requires = "password")]login: bool,
}fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
Usage: test_clap [OPTIONS]Options:-u, --username <USERNAME> -p, --password <PASSWORD> -l, --login 必须和 --username/--password 一起使用-h, --help Print help
参数互斥
conflicts_with
conflicts_with是两两互斥
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {/// 输出 JSON 格式#[arg(long, conflicts_with = "pretty")]json: bool,/// 美化输出#[arg(long, conflicts_with = "json")]pretty: bool,
}
fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
# 单独使用json
target/debug/test_clap --json
cli: MyCli { json: true, pretty: false }# 单独使用pretty
target/debug/test_clap --pretty
cli: MyCli { json: false, pretty: true }# 报错
target/debug/test_clap --json --pretty
conflicts_with_all
用于一个参数同时与多个参数互斥
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {/// 简洁模式,与其他详细模式互斥#[arg(short, long, conflicts_with_all = ["verbose", "debug", "trace"])]quiet: bool,#[arg(short, long)]verbose: bool,#[arg(long)]debug: bool,#[arg(long)]trace: bool,
}
fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
Usage: test_clap [OPTIONS]Options:-q, --quiet 简洁模式,与其他详细模式互斥-v, --verbose --debug --trace -h, --help Print help
# 单独用
cargo run -- --quiet
cargo run -- --verbose
cargo run -- --debug# quiet 和任何详细模式冲突
cargo run -- --quiet --verbose # 报错
cargo run -- --quiet --debug # 报错
cargo run -- --quiet --trace # 报错
独占类型
exclusive
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {// -q/--quiet不能和其他任何参数混用#[arg(short, long, exclusive = true)]quiet: bool,#[arg(short, long)]verbose: bool,#[arg(short, long)]debug: bool,#[arg(short, long)]trace: bool,
}
fn main() {let cli = MyCli::parse();println!("cli: {:?}", cli);
}
target/debug/test_clap -v -d
cli: MyCli { quiet: false, verbose: true, debug: true, trace: false }# 报错,不能和-q使用
target/debug/test_clap -v -d -q
value_parser参数验证
value_parser!(T)
基础类型转换
use clap::Parser;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, value_parser = clap::value_parser!(u16))]port: u16,#[arg(short, long, value_parser = clap::value_parser!(f64))]threshold: f64,#[arg(short, long, value_parser = clap::value_parser!(bool))]debug: bool,
}
范围验证
#[derive(Parser, Debug)]
struct MyCli {// 端口号范围 1024-65535#[arg(short, long, value_parser = clap::value_parser!(u16).range(1024..=65535))]port: u16,// 重试次数 1-10#[arg(short, long, value_parser = clap::value_parser!(u8).range(1..=10))]retry: u8,// 浮点范围 0.0-1.0#[arg(long, value_parser = clap::value_parser!(f64).range(0.0..=1.0))]ratio: f64,
}
网络类型
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddr};#[derive(Parser, Debug)]
struct MyCli {#[arg(long, value_parser = clap::value_parser!(Ipv4Addr))]ip: Ipv4Addr,#[arg(long, value_parser = clap::value_parser!(SocketAddrV4))]bind: SocketAddrV4,#[arg(long, value_parser = clap::value_parser!(SocketAddr))]addr: SocketAddr,
}
路径类型
use std::path::PathBuf;#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, value_parser = clap::value_parser!(PathBuf))]config: PathBuf,#[arg(short, long, value_parser = clap::value_parser!(PathBuf))]output: Option<PathBuf>,
}
字符串验证
#[derive(Parser, Debug)]
struct MyCli {// String 基本不需要 value_parser,但显式写也可以#[arg(short, long, value_parser = clap::value_parser!(String))]name: String,// OsString 用于非 UTF-8 路径#[arg(short, long, value_parser = clap::value_parser!(std::ffi::OsString))]path: std::ffi::OsString,
}
自定义类型(需实现 FromStr)
use clap::Parser;
use std::str::FromStr;#[derive(Debug, Clone)]
struct Color(u8, u8, u8);impl FromStr for Color {type Err = String;fn from_str(s: &str) -> Result<Self, Self::Err> {let v: Vec<u8> = s.split(',').map(|p| p.parse().map_err(|_| "无效数字")).collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())?;if v.len() != 3 {return Err("格式必须是 R,G,B".to_string());}Ok(Color(v[0], v[1], v[2]))}
}#[derive(Parser, Debug)]
struct MyCli {#[arg(short, long, value_parser = clap::value_parser!(Color))]color: Color,
}
容器类型
#[derive(Parser, Debug)]
struct MyCli {// 多次传参收集#[arg(short, long, value_parser = clap::value_parser!(u32))]ports: Vec<u32>,// 可选参数#[arg(short, long, value_parser = clap::value_parser!(String))]name: Option<String>,
}
自定义验证规则
案例
use clap::Parser;// 自定义解释器
fn parse_positive(s: &str) -> Result<u32, String> {let n: u32 = s.parse().map_err(|_| "Not a number")?;if n > 0 { Ok(n) } else { Err("Must be positive".into()) }
}#[derive(Parser, Debug)]
struct Cli {// parse_positive传入的是&str#[arg(long, value_parser = parse_positive)]age: u32,#[arg(long, value_parser = parse_positive, num_args = 1..)]ages: Vec<u32>,
}
fn main() {let cli = Cli::parse();println!("age: {}", cli.age);println!("ages: {}", cli.ages);
}
验证规则
cargo run -- --ages 10,20,30
# "10,20,30" 会被拆成 "10", "20", "30",分别调用 parse_positive
命令行输入: --ages 10 --ages 20 --ages 30↓ ↓parse_positive("10") → Ok(10)parse_positive("20") → Ok(20)parse_positive("30") → Ok(30)↓ages: Vec<u32> = [10, 20, 30]
