argparse的基本使用--参数解析

文章目录

    • argparse
    • 开始使用
      • 位置参数
      • 可选参数
      • 使用flag()函数
      • 必选参数
      • is_used("--arg")
      • 重复和互斥的可选参数
      • 负数参数
      • 将位置参数和可选参数组合起来
      • 打印帮助
      • 参数列表
      • 复合参数
      • 数值类型转换
      • 默认的-h和-v
      • 收集剩余参数
      • 父子解析器
      • 解析未知参数
      • 自定义前缀字符
      • 自定义分配字符

argparse

  • 项目地址argparse

开始使用

位置参数

int positionalArguments(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");

    program.add_argument("square")
            .help("display the square of a given integer")
            .scan<'i', int>();

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        return 1;
    }

    auto input = program.get<int>("square");
    std::cout << (input * input) << std::endl;

    return 0;
}

控制台命令和输出

XHCompiler.exe 15
-----------------------------------------------------------------------------------------
225

可选参数

int optionalArguments(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");

    program.add_argument("--verbose")
            .help("increase output verbosity")
            .default_value(false)
            .implicit_value(true);

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    if (program["--verbose"] == true) {
        std::cout << "Verbosity enabled" << std::endl;
    }
}

控制台命令和输出

XHCompiler.exe --verbose
-----------------------------------------------------------------------------------------
Verbosity enabled

使用flag()函数

flag函数像上面的.default_value(false).implicit_value(true);一样,是它的简写

int optionalArguments(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");

    program.add_argument("--verbose")
            .help("increase output verbosity")
            .flag();

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    if (program["--verbose"] == true) {
        std::cout << "Verbosity enabled" << std::endl;
    }
}

这里不在重复结果

必选参数

在某些情况下,我们需要一些必选参数,我们只要在可选参数中增加required()来表示即可

program.add_argument("-o", "--output")
  .required()
  .help("specify the output file.");

如果我们给该参数加了默认值,即可编程非必要参数,但是实际使用的时候该参数是以默认值形式存在的

program.add_argument("-o", "--output")
  .default_value(std::string("-"))
  .required()
  .help("specify the output file.");
int requiredArguments(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");

    program.add_argument("--verbose")
            .help("increase output verbosity")
            .flag();

    program.add_argument("-o", "--output")
            .required()
            .help("specify the output file.");


    program.add_argument("-b", "--base")
            .default_value(std::string("-"))
            .required()
            .help("specify the base.");

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    auto output = program.get<std::string>("--output");
    std::cout << output << std::endl;
    auto base = program.get<std::string>("--base");
    std::cout << base << std::endl;
    return 0;
}

控制台命令和输出

XHCompiler.exe -o "aaa" -b "bbb"
-----------------------------------------------------------------------------------------
aaa
bbb

is_used(“–arg”)

auto explicit_verbose = program.is_used("--verbose");
std::cout << explicit_verbose << std::endl;

使用is_used(“–arg”)来判断可选参数是否被使用, 可以在上面例子中加入如下代码,则输出的时候会输出你是否使用了verbose这个参数

重复和互斥的可选参数

  • 重复的可选参数
program.add_argument("--color")
  .default_value<std::vector<std::string>>({ "orange" })
  .append()
  .help("specify the cat's fur color");

try {
  program.parse_args(argc, argv);    // Example: ./main --color red --color green --color blue
}
catch (const std::exception& err) {
  std::cerr << err.what() << std::endl;
  std::cerr << program;
  std::exit(1);
}

auto colors = program.get<std::vector<std::string>>("--color");  // {"red", "green", "blue"}
int verbosity = 0;
program.add_argument("-V", "--verbose")
  .action([&](const auto &) { ++verbosity; })
  .append()
  .default_value(false)
  .implicit_value(true)
  .nargs(0);

program.parse_args(argc, argv);    // Example: ./main -VVVV

std::cout << "verbose level: " << verbosity << std::endl;    // verbose level: 4
  • 互斥的可选参数
auto &group = program.add_mutually_exclusive_group();
group.add_argument("--first");
group.add_argument("--second");

负数参数

int negativeNumbers(int argc, char *argv[])
{
    argparse::ArgumentParser program;

    program.add_argument("integer")
            .help("Input number")
            .scan<'i', int>();

    program.add_argument("floats")
            .help("Vector of floats")
            .nargs(4)
            .scan<'g', float>();

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }
    auto colors = program.get<std::vector<float>>("floats");
    auto inta = program.get<int>("integer");
    std::cout << colors[0] << std::endl;
    std::cout <<inta << std::endl;
    return 0;
}

输出结果

XHCompiler.exe -2 -2.2 -3.3 -4.4 -5.5
----------------------------------------------
-2.2
-2

将位置参数和可选参数组合起来

int compareArgs(int argc, char *argv[])
{
    argparse::ArgumentParser program;

    program.add_argument("square")
            .help("display the square of a given number")
            .scan<'i', int>();

    program.add_argument("--verbose")
            .default_value(false)
            .implicit_value(true);

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    int input = program.get<int>("square");

    if (program["--verbose"] == true) {
        std::cout << "The square of " << input << " is " << (input * input) << std::endl;
    }
    else {
        std::cout << (input * input) << std::endl;
    }
    return 0;
}
E:\XHCompiler\cmake-build-debug>XHCompiler.exe 15
225

E:\XHCompiler\cmake-build-debug>XHCompiler.exe 15 --verbose
The square of 15 is 225

E:\XHCompiler\cmake-build-debug>XHCompiler.exe --verbose 15
The square of 15 is 225

打印帮助

int main(int argc, char *argv[]) {
    int ret = 0;
//    ret = positionalArguments(argc, argv);
//    ret = optionalArguments(argc, argv);
//    ret = requiredArguments(argc, argv);
//    ret = negativeNumbers(argc, argv);
//    ret = compareArgs(argc, argv);


    argparse::ArgumentParser program("main");
    program.add_argument("thing").help("Thing to use.").metavar("THING");
    program.add_argument("--member").help("The alias for the member to pass to.").metavar("ALIAS");
    program.add_argument("--verbose").default_value(false).implicit_value(true);

    program.add_description("Forward a thing to the next member.");
    program.add_epilog("Possible things include betingalw, chiz, and res.");

    program.parse_args(argc, argv);

    std::cout << program << std::endl;

    return ret;
}

输出结果

E:\XHCompiler\cmake-build-debug>XHCompiler.exe --help
Usage: main [--help] [--version] [--member ALIAS] [--verbose] THING

Forward a thing to the next member.

Positional arguments:
  THING           Thing to use.

Optional arguments:
  -h, --help      shows help message and exits
  -v, --version   prints version information and exits
  --member ALIAS  The alias for the member to pass to.
  --verbose

Possible things include betingalw, chiz, and res.

参数列表

我们可以说使用nargs(int) 来确定参数个数。也可是使用scan(‘g’,float)来确定输入和类型后续复合参数来确定

int paramsList(int argc, char *argv[])
{
    argparse::ArgumentParser program;

    program.add_argument("-i", "--input_files")
            .help("The list of input files")
            .nargs(2);

    try {
        program.parse_args(argc, argv);   // Example: ./main --input_files config.yml System.xml
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    auto files = program.get<std::vector<std::string>>("--input_files");  // {"config.yml", "System.xml"}

    for(auto file : files)
    {
        std::cout << file << " ";
    }
    std::cout << std::endl;
    return 0;
}

输出结果

E:\XHCompiler\cmake-build-debug>XHCompiler.exe --input_files "aa aa" "bb"
aa aa bb

E:\XHCompiler\cmake-build-debug>XHCompiler.exe --input_files aa bb
aa bb

复合参数

int compoundParamsList(int argc, char *argv[])
{
    argparse::ArgumentParser program;

    program.add_argument("-a")
            .default_value(false)
            .implicit_value(true);

    program.add_argument("-b")
            .default_value(false)
            .implicit_value(true);

    program.add_argument("-c")
            .nargs(2)
            .default_value(std::vector<float>{0.0f, 0.0f})
            .scan<'g', float>();

    try {
        program.parse_args(argc, argv);                  // Example: ./main -abc 1.95 2.47
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    auto a = program.get<bool>("-a");                  // true
    auto b = program.get<bool>("-b");                  // true
    auto c = program.get<std::vector<float>>("-c");    // {1.95, 2.47}
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    for(auto file : c)
    {
        std::cout << file << " ";
    }
    std::cout << std::endl;
    return 0;
}

输出结果

E:\XHCompiler\cmake-build-debug>XHCompiler.exe -abc 1.0 2.0
1
1
1 2

数值类型转换

我们在使用scan()函数的时候使用了’g’这个,这些转换有一些预定类型,如下:

Shape interpretation
‘a’ or ‘A’ 十六进制浮点数
‘e’ or ‘E’ 科学记数法(浮点数)
‘f’ or ‘F’ 固定表示法(浮点)
‘g’ or ‘G’ 一般形式(固定形式或科学形式)
‘d’ 十进制
‘i’ std::from_chars带基数的语法 == 10
‘o’ 八进制(无符号)
‘u’ 十进制(无符号)
‘x’ or ‘X’ 十六进制(无符号)

默认的-h和-v

对于默认的-h和-v如果我们需要自己的,可以使用下列函数禁用默认的参数

int defaultCommand(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe", "1.0"
                                     , argparse::default_arguments::none);

    program.add_argument("-h", "--help")
            .action([=](const std::string& s) {
                std::cout << program.help().str();
            })
            .default_value(false)
            .help("shows help message")
            .implicit_value(true)
            .nargs(0);
    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }
    return 0;
}

收集剩余参数

只需要在参数使用remaining()函数即可

int remainingParamsList(int argc, char *argv[])
{
    argparse::ArgumentParser program;

    program.add_argument("-o")
            .default_value(std::string("a.out"));

    program.add_argument("files")
            .remaining();

    program.add_argument("-m")
            .default_value(std::string("a.out"));

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        std::exit(1);
    }

    try {
        auto files = program.get<std::vector<std::string>>("files");
        std::cout << files.size() << " files provided" << std::endl;
        for (auto& file : files)
            std::cout << file << std::endl;
    } catch (std::logic_error& e) {
        std::cout << "No files provided" << std::endl;
    }
    return 0;
}

输出

E:\XHCompiler\cmake-build-debug>XHCompiler.exe aa bb ccbb ddfb
4 files provided
aa
bb
ccbb
ddfb

注意:请记住将所有可选参数放在其余参数之前。如果可选参数放在其余参数之后,它也将被视为剩余参数:

父子解析器

int parentAndChildParamsList(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe");

    // git add subparser
    argparse::ArgumentParser add_command("add");
    add_command.add_description("Add file contents to the index");
    add_command.add_argument("files")
            .help("Files to add content from. Fileglobs (e.g.  *.c) can be given to add all matching files.")
            .remaining();

    // git commit subparser
    argparse::ArgumentParser commit_command("commit");
    commit_command.add_description("Record changes to the repository");
    commit_command.add_argument("-a", "--all")
            .help("Tell the command to automatically stage files that have been modified and deleted.")
            .default_value(false)
            .implicit_value(true);

    commit_command.add_argument("-m", "--message")
            .help("Use the given  as the commit message.");

    // git cat-file subparser
    argparse::ArgumentParser catfile_command("cat-file");
    catfile_command.add_description("Provide content or type and size information for repository objects");
    catfile_command.add_argument("-t")
            .help("Instead of the content, show the object type identified by .");

    catfile_command.add_argument("-p")
            .help("Pretty-print the contents of  based on its type.");

    // git submodule subparser
    argparse::ArgumentParser submodule_command("submodule");
    submodule_command.add_description("Initialize, update or inspect submodules");
    argparse::ArgumentParser submodule_update_command("update");
    submodule_update_command.add_description("Update the registered submodules to match what the superproject expects");
    submodule_update_command.add_argument("--init")
            .default_value(false)
            .implicit_value(true);
    submodule_update_command.add_argument("--recursive")
            .default_value(false)
            .implicit_value(true);
    submodule_command.add_subparser(submodule_update_command);

    program.add_subparser(add_command);
    program.add_subparser(commit_command);
    program.add_subparser(catfile_command);
    program.add_subparser(submodule_command);

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        return 1;
    }
    return 0;
}
 
  

执行输出自己尝试。

  • 解析器具有is_subcommand_used(),该命令用来检查是否使用了子命令
  • 我们还可以用下列函数获取子解析器
argparse::ArgumentParser program("test");

program.add_argument("--dir");
program.at("--dir").default_value(std::string("/home/user"));

program.add_subparser(argparse::ArgumentParser{"walk"});
program.at<argparse::ArgumentParser>("walk").add_argument("depth");

解析未知参数

int unknownParamsList(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe");
    program.add_argument("--foo").implicit_value(true).default_value(false);
    program.add_argument("bar");

    auto unknown_args =
            program.parse_known_args({"test", "--foo", "--badger", "BAR", "spam"});

    assert(program.get<bool>("--foo") == true);
    assert(program.get<std::string>("bar") == std::string{"BAR"});
    assert((unknown_args == std::vector<std::string>{"--badger", "spam"}));
    return 0;
}

自定义前缀字符

int selfPrefixChar(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe");
    program.set_prefix_chars("-+/");

    program.add_argument("+f");
    program.add_argument("--bar");
    program.add_argument("/foo");

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        return 1;
    }

    if (program.is_used("+f")) {
        std::cout << "+f    : " << program.get("+f") << "\n";
    }

    if (program.is_used("--bar")) {
        std::cout << "--bar : " << program.get("--bar") << "\n";
    }

    if (program.is_used("/foo")) {
        std::cout << "/foo  : " << program.get("/foo") << "\n";
    }

    return 0;
}

自定义分配字符

int selfAssignmentChar(int argc, char *argv[])
{
    argparse::ArgumentParser program("XHCompiler.exe");
    program.set_prefix_chars("-+/");
    program.set_assign_chars("=:");

    program.add_argument("--foo");
    program.add_argument("/B");

    try {
        program.parse_args(argc, argv);
    }
    catch (const std::exception& err) {
        std::cerr << err.what() << std::endl;
        std::cerr << program;
        return 1;
    }

    if (program.is_used("--foo")) {
        std::cout << "--foo : " << program.get("--foo") << "\n";
    }

    if (program.is_used("/B")) {
        std::cout << "/B    : " << program.get("/B") << "\n";
    }
    return 0;
}

输出

E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B a
/B    : a

E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B=a
/B    : a

E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B:a
/B    : a

你可能感兴趣的:(C/C++,c++)