PDA

View Full Version : Split strings using QStringList::split() but ignore quotes.



halvors
24th December 2010, 18:44
I need to split a QStringList but ignore anything inside quotes ("")

Here is my code:


QStringList str;
str = cmd.split(QRegExp(" ")); // TODO: Ignore spaces (" ") inside quotes ("")


Thanks for any help :D

JackHammer
25th December 2010, 05:36
First use QString::remove() on your string "cmd" to remove the spaces or whatever. Then use QString::split().

halvors
25th December 2010, 12:05
How should that code be:

When try this:


QStringList str;
str = cmd.remove(QRegExp("\\s+")).split(" "); // TODO: Ignore spaces (" ") inside quotes ("")


I get this error: /home/halvors/Prosjekter/openrcon/openrcon-build-desktop/src/../../trunk/src/BFBC2Connection.cpp:100: error: passing ‘const QString’ as ‘this’ argument of ‘QString& QString::remove(const QRegExp&)’ discards qualifiers

halvors
2nd January 2011, 19:10
No ideas? Can someone please try svolve this :D

CamiCa
3rd February 2011, 16:45
You can try this:


QStringList tmpList = cmd.split(QRegExp("\"")); // Split by "
bool inside = false;
list.clear();
foreach (QString s, tmpList) {

if (inside) { // If 's' is inside quotes ...

list.append(s); // ... get the whole string
} else { // If 's' is outside quotes ...

list.append(s.split(QRegExp("\\s+"), QString::SkipEmptyParts)); // ... get the splitted string
}
inside = !inside;
}

Phlucious
14th February 2012, 00:59
This is a great post, and I just used it in my application.

However, you need to account for the case where the CSV string begins with a quote. A couple small modifications will accomplish this:


bool inside = (cmd.at(0) == "\""); //true if the first character is "
QStringList tmpList = cmd.split(QRegExp("\""), QString::SkipEmptyParts); // Split by " and make sure you don't have an empty string at the beginning
QStringList csvlist;
foreach (QString s, tmpList) {
if (inside) { // If 's' is inside quotes ...
csvlist.append(s); // ... get the whole string
} else { // If 's' is outside quotes ...
csvlist.append(s.split(" ", QString::SkipEmptyParts)); // ... get the splitted string
}
inside = !inside;
}

saylijawale
6th February 2017, 07:22
does the case will be the same if I want to ignore the space after comma , and split only with whitespace which has no comma before it?

jefftee
6th February 2017, 19:10
This is what I use to parse CSV data. If you're not very familiar with regular expressions, it will make your head explode... :) If you are familiar, it will just give you a migraine!



QStringList TableSync::parseCsvFields(const QString &line, const QChar delimiter)
{
QString temp = line;
QString field;
QStringList field_list;

// regex explaination
//
// /(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)/g
// (?:^|,) Non-capturing group
// 1st Alternative: ^
// ^ assert position at start of the string
// 2nd Alternative: ,
// , matches the character , literally
// 1st Capturing group (\"(?:[^\"]+|\"\")*\"|[^,]*)
// 1st Alternative: \"(?:[^\"]+|\"\")*\"
// \" matches the character " literally
// (?:[^\"]+|\"\")* Non-capturing group
// Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
// 1st Alternative: [^\"]+
// [^\"]+ match a single character not present in the list below
// Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
// \" matches the character " literally
// 2nd Alternative: \"\"
// \" matches the character " literally
// \" matches the character " literally
// \" matches the character " literally
// 2nd Alternative: [^,]*
// [^,]* match a single character not present in the list below
// Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
// , the literal character ,
// g modifier: global. All matches (don't return on first match)
//

QString regex = "(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)";
regex.replace(",", delimiter);

QRegularExpression re(regex);

if (temp.right(1) == "\n") temp.chop(1);

QRegularExpressionMatchIterator it = re.globalMatch(temp);

while (it.hasNext())
{
QRegularExpressionMatch match = it.next();
if (match.hasMatch())
{
field = match.captured(1);
if (field.left(1) == "\"" && field.right(1) == "\"")
field = field.mid(1, field.length()-2);
field_list.push_back(field);
}
}

return field_list;
}

Hope that helps.