我正在使用 boost::program_options
来解析我的命令行。现在,我通过表示文件的 --script
参数添加对批处理执行的支持,每行包含命令行选项,例如:
--src="\"z:\dev\veds\sqlexpress\Run 1.ved\"" --src-kind=bla --yz
--src=z:\dev\veds\sqlexpress\db.ebf
--src=z:\dev\veds\sqlexpress\db2.mdf
--src=db3
--src="\"z:\dev\veds\sqlite\Run 41 (Run 23).ved\""
--src=z:\dev\veds\sqlite\ws_results_db_2012_01_15_18_37_03.db3
--src=z:\dev\veds\mysql\10.ved
--src=z:\dev\veds\mysql\db
文件中的每一行表示我的工具的一次执行,并列出了该特定执行的命令行选项。
问题是读取脚本文件会产生完整的行,这些行没有被分解成单独的命令行选项。但是,必须有 argc
和 argv
才能使用 boost::program_options
,也就是说,这取决于有人将命令行分为不同的选择。
我不能简单地用空格分隔,因为有些值包含空格,因此它们用双引号括起来,甚至嵌套双引号。
另一方面,我不想为每组命令行选项从操作系统命令提示符运行该工具,因为 Bootstrap 很昂贵——这也是我首先引入脚本功能的原因。
是否有一种简单的方法可以像操作系统那样将行分成命令行参数?
谢谢。
最佳答案
好的,我知道了。这是我的代码:
string script;
{
ifstream file(scriptPath.c_str());
file.seekg(0, ios::end);
script.resize(file.tellg());
file.seekg(0, ios::beg);
file.read(const_cast<char *>(script.c_str()), script.size());
}
boost::replace_all(script, "\\", "\\\\"); // Escape the backslashes
boost::replace_all(script, "\\\\\"", "\\\""); // Except for those escaping the quotes
boost::trim_right_if(script, is_space_or_zero); // There are extra '\0' in the string, because the file is read as text, but its length was computed as binary
vector<string> lines;
boost::split(lines, script, boost::is_any_of("\n")); // I prefer getting a string line iterator here, the question is how?
escaped_list_separator<char> sep('\\', ' ', '"');
int res = 0;
BOOST_FOREACH (const string& line, lines)
{
// reset the command line variables here, since this is like a new execution
// Tokenize the command line, respecting escapes and quotes
tokenizer<escaped_list_separator<char>> tok(line, sep);
vector<string> args(tok.begin(), tok.end());
po::variables_map vm;
po::store(po::command_line_parser(args).options(options).run(), vm);
res += run(vm);
}
我正在使用 http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/打破界限。效果很好。
关于c++:如何将字符串分解(不解析)为命令行参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8964307/