Extract parameters from string, included quoted regions, in Qt

前端 未结 3 1435
梦如初夏
梦如初夏 2021-01-22 07:27

I have a Qt5/C++ program which receives a QString containing a program name and possibly parameters. I need to split this QString into multiple strings. For example, the strin

相关标签:
3条回答
  • 2021-01-22 07:33

    There are two aspects of your task:

    1. Splitting of the command line into arguments. This needs to be implemented from scratch.

    2. Processing of the arguments to extract parameters and their values. Since Qt 5.2, you can use QCommandLineParser to do that.

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

    Output:

    param1
    param2: "2 2"
    param3: ("1", "2", "3")
    param4: "4"
    

    QDebug quotes the strings it outputs. The strings themselves don't contain any quotes.

    0 讨论(0)
  • 2021-01-22 07:38

    I'm not familiar with the particulars of Qt, however with a quick look at the documentation for QString, here, I believe that the following code should work (albeit inefficiently).

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

    Again, I do not use any Qt libraries, and this code is untested, but, if I understand the documentation, it should work.

    As far as the -p 4 bit goes, that is not possible with your current syntax for the other arguments.

    0 讨论(0)
  • 2021-01-22 07:38

    Extract parameters from string, included quoted regions, in Qt

    When parsing any "escaped" or quoted string: splitArgs (from KF5) was immensely useful.

    The following source code manages "escaping" and more; from

        one two a\ b "c d e"
    

    it prints

        one
        two
        a b
        c d e
    

    The core of the source code is just a splitArgs call:

    #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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题