如果我理解正確的問題,要分析以下形式的命令行選項:
[--generic-option ...] cmd [--cmd-specific-option ... ]
這裏是我的榜樣解決方案。爲了清楚起見,我將忽略任何驗證代碼,但希望您可以看到它將如何相當簡單地添加。
在這個例子中,我們有「ls」子命令,可能還有其他的。每個子命令都有一些特定的選項,另外還有一些通用選項。所以讓我們從解析通用選項和命令名開始。
po::options_description global("Global options");
global.add_options()
("debug", "Turn on debug output")
("command", po::value<std::string>(), "command to execute")
("subargs", po::value<std::vector<std::string> >(), "Arguments for command");
po::positional_options_description pos;
pos.add("command", 1).
add("subargs", -1);
po::variables_map vm;
po::parsed_options parsed = po::command_line_parser(argc, argv).
options(global).
positional(pos).
allow_unregistered().
run();
po::store(parsed, vm);
請注意,我們爲命令名稱和命令選項創建了多個位置選項。
現在我們分支到相關的命令名並重新解析。我們現在不用傳入原始的argc
和argv
,而是以字符串數組的形式傳遞無法識別的選項。 collect_unrecognized
函數可以提供這一點 - 我們所要做的就是刪除(位置)命令名,並重新解析相關的options_description
。
std::string cmd = vm["command"].as<std::string>();
if (cmd == "ls")
{
// ls command has the following options:
po::options_description ls_desc("ls options");
ls_desc.add_options()
("hidden", "Show hidden files")
("path", po::value<std::string>(), "Path to list");
// Collect all the unrecognized options from the first pass. This will include the
// (positional) command name, so we need to erase that.
std::vector<std::string> opts = po::collect_unrecognized(parsed.options, po::include_positional);
opts.erase(opts.begin());
// Parse again...
po::store(po::command_line_parser(opts).options(ls_desc).run(), vm);
請注意,我們使用相同的variables_map
有特定命令的選項作爲通用的。由此我們可以執行相關操作。
這裏的代碼段來自一個可編譯源文件,其中包含一些單元測試。你可以找到它的要求here。請隨意下載並使用它。
優秀的答案,以完整的例子來啓動。謝謝! --DD – ddevienne 2014-06-23 11:56:38
太棒了! – 2015-01-16 17:30:41