C++按空格拆分命令行参数,不拆分含空格的参数值
如何用Boost内置工具实现带多值选项的命令行参数字符串拆分
你有如下命令行参数字符串:
"-opt1 val1 -opt2 val1 val2 -opt3 val3"
使用boost::split按空格拆分:
boost::split(target_vector, inputString, boost::is_any_of(" "), boost::token_compress_on);
得到的结果是:
["-opt1", "val1", "-opt2", "val1", "val2", "-opt3", "val3"]
但期望的结果是将-opt2后的val1 val2作为单个元素:
["-opt1", "val1", "-opt2", "val1 val2", "-opt3", "val3"]
以下是几种Boost内置的解决方案:
方案1:使用Boost.Program_options(推荐)
Boost专门提供了Boost.Program_options库用于解析命令行参数,原生支持多值选项,无需手动拆分字符串。示例代码如下:
#include <boost/program_options.hpp> #include <vector> #include <string> #include <iostream> namespace po = boost::program_options; int main() { std::string input = "-opt1 val1 -opt2 val1 val2 -opt3 val3"; // 将字符串转换为argc/argv格式的参数列表 std::vector<std::string> args; boost::split(args, input, boost::is_any_of(" "), boost::token_compress_on); // 定义选项描述 po::options_description desc("Allowed options"); desc.add_options() ("opt1", po::value<std::string>(), "option 1") ("opt2", po::value<std::vector<std::string>>()->multitoken(), "option 2 with multiple values") ("opt3", po::value<std::string>(), "option 3"); // 解析参数 po::variables_map vm; po::store(po::command_line_parser(args).options(desc).run(), vm); po::notify(vm); // 整理成目标格式的向量 std::vector<std::string> result; if (vm.count("opt1")) { result.push_back("-opt1"); result.push_back(vm["opt1"].as<std::string>()); } if (vm.count("opt2")) { result.push_back("-opt2"); // 将多值合并为单个字符串 std::vector<std::string> vals = vm["opt2"].as<std::vector<std::string>>(); std::string val_str; for (size_t i = 0; i < vals.size(); ++i) { if (i > 0) val_str += " "; val_str += vals[i]; } result.push_back(val_str); } if (vm.count("opt3")) { result.push_back("-opt3"); result.push_back(vm["opt3"].as<std::string>()); } // 输出验证 for (const auto& s : result) { std::cout << "\"" << s << "\" "; } }
这个方案的优势在于它是专门为命令行参数设计的,支持类型校验、默认值、帮助信息生成等功能,比手动拆分更健壮。
方案2:使用Boost.Regex实现自定义拆分
如果你只需要基于字符串拆分的轻量方案,可以用Boost.Regex匹配每个选项及其对应的多值内容,示例代码如下:
#include <boost/regex.hpp> #include <boost/algorithm/string.hpp> #include <vector> #include <string> #include <iostream> int main() { std::string input = "-opt1 val1 -opt2 val1 val2 -opt3 val3"; // 正则表达式:匹配以'-'开头的选项,以及后续直到下一个选项前的所有内容 boost::regex opt_re(R"((-\w+)\s+((?:(?!-\w+).)*))"); boost::sregex_iterator it(input.begin(), input.end(), opt_re); boost::sregex_iterator end; std::vector<std::string> result; for (; it != end; ++it) { // 添加选项名 result.push_back((*it)[1].str()); // 提取值并去除前后空格 std::string val = boost::algorithm::trim_copy((*it)[2].str()); result.push_back(val); } // 输出验证 for (const auto& s : result) { std::cout << "\"" << s << "\" "; } }
这段代码会直接生成你期望的向量结构,无需额外处理拆分后的元素。
方案3:自定义分隔谓词(不推荐)
虽然boost::split本身没有直接支持这种拆分逻辑,但你可以自定义分隔谓词,不过这种方式需要处理上下文(判断空格后是否是选项开头),实现起来比较繁琐,不如上面两种方案简洁可靠,这里不展开详细代码。
内容的提问来源于stack exchange,提问作者Pit Digger
相关产品推荐
相关产品推荐

