当前位置: 首页 > 知识库问答 >
问题:

rust的clap如何传参数?

柯冯浩
2024-04-29
use std::fs::{File, OpenOptions};use std::io::{BufRead, BufReader, Seek, SeekFrom, Write};use std::path::Path;use std::thread;use std::time::Duration;use clap::{Command, arg};fn main() {    let mut log_file_path_str: &str = "";    let mut index_file_path_str: &str = "";    let matches = Command::new("watch_log")        .version("1.0")        .author("357888473@qq.com")        .about("watch log and handle log every line")        .subcommand_required(true)        .arg_required_else_help(true)        .subcommand(            Command::new("logpath")                .about("log's path")                .arg(arg!(--logpath <VALUE>).help("String").required(true)),        )        .subcommand(            Command::new("indexpath")                .about("index's path")                .arg(arg!(--indexpath <VALUE>).help("save read log's line count").required(true)),        ).get_matches();    match matches.subcommand() {        Some(("logpath", sub_matches)) => {            if let Some(input) = sub_matches.get_one::<String>("logpath") {                log_file_path_str = input;            }        },        Some(("indexpath", sub_matches)) => {            if let Some(input) = sub_matches.get_one::<String>("indexpath") {                index_file_path_str = input;            }        },        _ => unreachable!(),    }    let log_file_path = Path::new(log_file_path_str); // 日志文件路径    let index_file_path = Path::new(index_file_path_str); // 索引文件路径    loop {        let mut current_line_number = get_current_line_number(&index_file_path); // 获取上次读取的行数        let mut file = File::open(&log_file_path).unwrap(); // 打开日志文件        file.seek(SeekFrom::Start(0)).unwrap(); // 移动到文件开头        let reader = BufReader::new(&mut file);        let mut new_lines = false; // 用于标记是否有新的日志行读取        for line in reader.lines().skip(current_line_number as usize) {            let line = line.unwrap();            println!("{}", line);            current_line_number += 1; // 更新当前行数            new_lines = true;        }        if new_lines {            set_current_line_number(&index_file_path, current_line_number); // 更新索引文件中的行数        }        println!("等待新日志...");        thread::sleep(Duration::from_secs(1)); // 暂停1秒钟,然后重新开始循环    }}fn get_current_line_number(index_file_path: &Path) -> u64 {    if let Ok(index_content) = std::fs::read_to_string(index_file_path) {        // 读取索引文件中的内容,转换为已读行数        if let Ok(current_line_number) = index_content.trim().parse::<u64>() {            return current_line_number;        }    }    0 // 默认为0}fn set_current_line_number(index_file_path: &Path, line_number: u64) {    // 更新索引文件中的已读行数    let mut index_file = OpenOptions::new().write(true).create(true).truncate(true).open(index_file_path).unwrap();    writeln!(index_file, "{}", line_number).expect("无法写入索引文件");}

请教给为,我用rust 通过命令行传入两个参数 logpath 和 indexpath,但是在执行的时候从事报错,我的执行命令是:
cargo run -- logpath=hello.log --indexpath=index.txt

报错是 error: unexpected argument '--logpath' found
我试过各种命令哈,再比如:
cargo run -- --logpath=hello.log --indexpath=index.txt

我查了很多资料,都无法解决,请各位大佬看下我上边代码,看看是否是我哪里有问题造成的,应该如何传参,谢谢

共有2个答案

别锐
2024-04-29

我猜你可能没有理解什么是子命令和选项参数

./abc xxx --dir="/tmp"

其中 xxx 是子命令(sub command),而 --dir 是选项参数(option)

所以如果是根据你的代码你应该运行的命令是

cargo run -- logpath --logpath="hello.log"

输出大概是:

cargo run -- logpath --logpath="/tmp/abc.log"    Finished dev [unoptimized + debuginfo] target(s) in 0.04s     Running `target/debug/let-code logpath --logpath=/tmp/abc.log`123

因为你代码里面写了将 logpath 作为一个子命令,并且接收一个 --logpath 的选项。这挺奇怪的,所以我猜测你没理解。并且这样 --indexpath 是没有办法同时输入的。

我会认为你应该创建一个子命令 monitor 然后将 --logpth--indexpath 作为选项才对。当然由于不知道你的具体需求,所以没法给出更多建议。


我想你需要的是不是这样的实现:

use clap::{arg, Command};fn main() {    let mut log_file_path_str: &str = "";    let mut index_file_path_str: &str = "";    let matches = Command::new("watch_log")        .version("1.0")        .author("357888473@qq.com")        .about("watch log and handle log every line")        .subcommand_required(true)        .arg_required_else_help(true)        .subcommand(Command::new("monitor").about("log's path").args([            arg!(--logpath <VALUE>).help("String").required(true),            arg!(--indexpath <VALUE>).help("String").required(true),        ]))        .get_matches();    match matches.subcommand() {        Some(("monitor", sub_matches)) => {            if let Some(input) = sub_matches.get_one::<String>("logpath") {                log_file_path_str = input;            }            if let Some(input) = sub_matches.get_one::<String>("indexpath") {                index_file_path_str = input;            }        }        _ => unreachable!(),    }    println!("{}, {}", log_file_path_str, index_file_path_str);}
$ cargo run -- monitor --logpath="/tmp/abc.log" --indexpath="/tmp/ttt.log"/tmp/abc.log, /tmp/ttt.log
孟成文
2024-04-29

你的代码看起来是正确的,但是在使用 cargo run 命令来运行 Rust 程序时,你需要知道 cargo run 命令实际上会先构建你的项目,然后运行构建出的可执行文件。因此,传递给程序的参数实际上需要传递给这个可执行文件,而不是 cargo run 命令。

在你的情况下,你可能需要两步来运行你的程序。首先,你需要构建你的项目:

cargo build

然后,你可以直接运行构建出的可执行文件,并传递参数给它。在你的例子中,可执行文件的名字可能是 watch_log(这取决于你的 Cargo.toml 文件中 [package] 部分的 name 字段),因此你可以这样运行它:

./target/debug/watch_log logpath=hello.log indexpath=index.txt

或者,如果你正在使用 cargo 的默认配置(即,你的项目在 src/main.rs 文件中),那么构建出的可执行文件的名字应该是 target/debug/your_project_name,其中 your_project_name 是你在 Cargo.toml 文件的 [package] 部分定义的 name。所以,你可能需要这样运行它:

./target/debug/your_project_name logpath=hello.log indexpath=index.txt

注意,在这些命令中,我没有包含 -- 在参数前面,因为 clap 库会自动处理这种情况。--logpath--indexpath 是被 clap 定义为长选项的参数,所以你可以直接传递它们,而不需要 -- 前缀。

希望这能解决你的问题!如果你还有其他问题,欢迎继续提问。

 类似资料:
  • 各位好,我用rust的axum进行学习,现在有个问题,我提供的代码 第一个函数传了2个参数,一个是info,一个是header,问题是:第一个info加上后没问题,但函数如果加上第二个参数 下边一行.route中的api::post_foo就会报错,如果我把两个参数任意一个参数去掉,都不会报错。所以我就不知道该怎么办了,我其实是想拿到post的json数据,以及查看header,甚至想看reque

  • Rust教程没有解释如何从命令行获取参数。在所有示例中,< code>fn main()只显示了一个空参数列表。 从 访问命令行参数的正确方法是什么?

  • 问题内容: 我正在A中使用RUN指令安装rpm 但是,我想将值“ 2.3”作为参数传递。我的RUN指令应类似于: 哪里 问题答案: 您正在寻找和指导。这些是Docker 1.9中的新功能。查看https://docs.docker.com/engine/reference/builder/#arg。这将允许您添加到,然后使用构建。

  • 问题内容: 我是JavaScript和jQuery的新手。我想显示一个combobox-A,它是一个HTML ,其选择的内容位于onChange()的另一位置。 如何传递带有其select的完整组合框,以及如何在onChange事件触发时传递其他参数? 问题答案: function getComboA(selectObject) { 上面的示例为您提供OnChange事件上组合框的选定值。

  • 问题内容: 将参数传递给已编译的代码: 结果是: 显示已通过的用户名。 目的: 为了防止每次测试代码时都需要手动构建和运行代码,目的是编写一个能够测试参数传递的测试。 尝试 运行以下测试: 结果是: 问题 它看起来像那样不能够这个参数传递给函数的结果是不是 问题答案: 根据我的评论,第一个值是可执行文件本身的(路径),因此应解决您的问题。您可以从标准包中查看标志测试,他们正在做类似的事情。 另外,

  • 本文向大家介绍如何获取路由传过来的参数?相关面试题,主要包含被问及如何获取路由传过来的参数?时的应答技巧和注意事项,需要的朋友参考一下 如果使用方式传入的参数使用 接收 如果使用方式传入的参数使用接收 参考:路由组件传参