我有一个Qt5 / C ++程序,它接收一个包含程序名称和可能参数的QString。我需要将此QString拆分为多个字符串。例如,字符串
/tmp/myprog --param1 --param2=2 --param3="1 2 3" -p 4
应分成:
list[0]=/tmp/myprog
list[1]=--param1
list[2]=--param2=2
list[3]=--param3="1 2 3"
list[4]=-p 4
我的第一个想法是在空格上使用“split”方法,但这会破坏引用的param3。同样,参数4在-p和4之间没有:或=。
有一种简单的方法吗?我怀疑-p 4不可能轻易拆分,因为无法知道下面的两个项目是否在一起。
但是有分裂/正则表达式/其他方式来分割上述内容吗? (如果我们忽略-p 4是否可能?)
更新
相同的函数可以在没有--param或-p的情况下拆分字符串吗? <串口
abc "a a" "b b b" c
会变成
list[0]=abc
list[1]="a a"
list[2]="b b b"
list[3]=c
答案 0 :(得分:7)
您的任务有两个方面:
将命令行拆分为参数。这需要从头开始实施。
处理提取参数及其值的参数。从Qt 5.2开始,您可以使用QCommandLineParser
来执行此操作。
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDebug>
static QStringList splitCommandLine(const QString & cmdLine)
{
QStringList list;
QString arg;
bool escape = false;
enum { Idle, Arg, QuotedArg } state = Idle;
foreach (QChar const c, cmdLine) {
if (!escape && c == '\\') { escape = true; continue; }
switch (state) {
case Idle:
if (!escape && c == '"') state = QuotedArg;
else if (escape || !c.isSpace()) { arg += c; state = Arg; }
break;
case Arg:
if (!escape && c == '"') state = QuotedArg;
else if (escape || !c.isSpace()) arg += c;
else { list << arg; arg.clear(); state = Idle; }
break;
case QuotedArg:
if (!escape && c == '"') state = arg.isEmpty() ? Idle : Arg;
else arg += c;
break;
}
escape = false;
}
if (!arg.isEmpty()) list << arg;
return list;
}
int main(int argc, char * argv[])
{
QCoreApplication app(argc, argv);
QCommandLineParser parser;
parser.addHelpOption();
QCommandLineOption param1("param1");
QCommandLineOption param2("param2", "", "val2");
QCommandLineOption param3("param3", "", "val3");
QCommandLineOption param4("p", "", "val4");
parser.addOption(param1);
parser.addOption(param2);
parser.addOption(param3);
parser.addOption(param4);
if (true) {
// Parse a string
QString cmdLine("/tmp/myprog --param1 --param2=2\\ 2 --param3=\"1 2 3\" -p 4");
parser.parse(splitCommandLine(cmdLine));
} else {
// Parse a command line passed to this application
parser.process(app);
}
if (parser.isSet(param1)) qDebug() << "param1";
if (parser.isSet(param2)) qDebug() << "param2:" << parser.value(param2);
if (parser.isSet(param3)) {
QStringList values = parser.value(param3)
.split(' ', QString::SkipEmptyParts);
qDebug() << "param3:" << values;
}
if (parser.isSet(param4)) qDebug() << "param4:" << parser.value(param4);
return 0;
}
输出:
param1
param2: "2 2"
param3: ("1", "2", "3")
param4: "4"
QDebug
引用它输出的字符串。字符串本身不包含任何引号。
答案 1 :(得分:2)
我不熟悉Qt的细节,但是快速查看QString的文档here,我相信下面的代码应该工作(虽然效率低下)
#include<QString>
#include<vector>
vector<QString> list; //vector used for variable length parameter requirements
QString args; //The arguments string
bool quoteFlag = false;
for(int i=0; i<args.size(); i++){
QString qstr = "";
while(args.at(i) != QChar(' ') || quoteFlag){ //loops if character is not ' ' or is within a set of quotes
if(args.at(i) == QChar('\"'){
quoteFlag = !quoteflag; //basically says, "you are now within a set of quotes"
}
qstr += args.at(i); //add current character to qstr
i++
}
list.push_back(qstr) //add qstr to the argument list
}
同样,我不使用任何Qt库,并且此代码未经测试,但是,如果我理解文档,那么应该工作。
就-p 4
位而言,使用当前其他参数的语法是不可能的。
答案 2 :(得分:0)
从Qt
中的字符串,包含的引用区域中提取参数
解析任何“转义”或引用的字符串时:splitArgs
(来自KF5)非常有用。
以下源代码管理“转义”等等;来自
one two a\ b "c d e"
打印
one
two
a b
c d e
源代码的核心只是splitArgs
调用:
#include <QTextStream>
#include <KShell>
int main()
{
QString whole = "one two a\\ b \"c d e\"";
QTextStream(stdout) << whole << endl << "--------------------" << endl;
QStringList group = KShell::splitArgs("one two a\\ b \"c d e\"");
for (auto element: group) {
QTextStream(stdout) << element << endl;
}
}