c ++:如何断开(不解析)一个字符串到命令行参数? [英] c++: how to break (not parse) a string into command line arguments?

查看:131
本文介绍了c ++:如何断开(不解析)一个字符串到命令行参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 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(运行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



问题是,读取脚本文件会导致完整的脚本文件。行,它们不分成单独的命令行选项。但是,为了使用 boost :: program_options,必须有 argc argv / code>,即它取决于某人将命令行分成不同的选项。



我不能简单地用空格分隔,因为一些值包含空格,因此它们用双引号,甚至是嵌套的双引号括起来。



另一方面,我不想从操作系统命令提示符运行每个命令集线路选项,因为昂贵的引导 - 这是我首先引入脚本功能的原因。



有一个简单的方法来打破命令行行参数以相同的方式操作系统吗?



感谢。

解决方案

这是我的代码:

 字符串脚本; 
{
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,\\,\\\\); //转义反斜杠
boost :: replace_all(script,\\\\\,\\\\\); //除了那些转义引号
boost :: trim_right_if(script,is_space_or_zero); //在字符串中有额外的'\0',因为文件被读取为文本,但其长度计算为二进制
vector< string>线;
boost :: split(lines,script,boost :: is_any_of(\\\
)); //我更喜欢在这里得到一个字符串行迭代器,问题是如何?
escaped_list_separator< char> sep('\\','',''');
int res = 0;
BOOST_FOREACH(const string& line,lines)
{
//重置命令行变量这里,因为这是一个新的执行

//令牌命令行,尊重转义和引号
tokenizer< escaped_list_separator< char>> tok );
vector< string> args(tok.begin(),tok.end());

po :: variables_map vm; :command_line_parser(args).options(options).run(),vm);

res + = run(vm);
}



我使用 http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/ 打破线条,效果非常好。


I am using boost::program_options to parse my command line. Now, I am adding support for batch execution, by means of a --script argument denoting a file, containing command line options on every line, for instance:

--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

Each line in the file denotes a single execution of my tool and lists the command line options for this particular execution.

The problem is that reading the script file yields complete lines, which are not broken into individual command line options. But, one has to have argc and argv in order to use boost::program_options, i.e. it depends on someone to break the command line into different options.

I cannot simply break by spaces, because some values contain spaces and hence they are enclosed with double quotes, even nested double quotes.

On the other hand, I do not want to run the tool from the OS command prompt for each set of command line options, because of the expensive bootstrap - the reason why I am introducing the script feature in the first place.

Is there a simple way to break the lines into the command line arguments in the same way the OS does it?

Thanks.

解决方案

OK, I have it figured out. Here is my code:

  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);
  }

I am using http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/ to break the lines. Works very well.

这篇关于c ++:如何断开(不解析)一个字符串到命令行参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆