PDA

View Full Version : Split QString only at unescaped slash



QphiuchuS
20th January 2015, 11:53
Hello!

Let's assume I have the following QString: "hello/world/how\/are/you".

I would like to split the string into a QStringList with the following content: {"hello", "world", "how\/are", "you"}. The best success so far I had with
QRegExp ex("[^\\\\]/"), but that unfortunately cuts off the last letter before the backslash. Is there a way to achive the desired split? BTW, I was only able to split the string if I escaped the backslash in "how\\/are" manually,
string.replace("\\", "\\\\") did not work, why is that?

BR

jefftee
20th January 2015, 16:23
You should consider QRegularExpression over QRegExp. QRegularExpression is compatible with Perl Compatible Regular Expressions (PCRE). The following QRegularExpression works for your test string (I didn't test extensively):


QRegularExpression re("(\\w+(?:\\\\\\/)*\\w*)?");

I didn't compile this, so I hope I didn't screw up the backslash quoting. The raw PCRE is (\w+(?:\\\/)*\w*)? and was tested at the awesome regex test site (another reason to use QRegularExpression over QRegExp):

https://regex101.com/

Good Luck

QphiuchuS
20th January 2015, 19:40
Thank you very much for your input. Unfortunately your suggestion does not provide the desired result:



""
""
"/"
""
"/"
""
"/"
""
"/"
""
""


Is it possible to logically concatenate regular expressions? Something like
"/" AND NOT "\/"

jefftee
20th January 2015, 20:38
Sorry, the first regex worked with QRegularExpression::globalMatch, try this one with QString::split:


QString str = "hello/world/how\\/are/you";
QRegularExpression re("\\/(?<!\\\\\\/)");
QStringList strlist = str.split(re);

ChrisW67
20th January 2015, 20:47
You are looking for a negative look-behind assertion. The bare regular expression looks like this:


(?<!\\)\/
when used on jthomps testing web site and matches only the slashes you wish to split on. In C++ code that would look like this for QRegularExpression:


QRegularExpression re("(?<!\\\\)/");

QphiuchuS
20th January 2015, 21:16
Thank you again, that works, but only if the backslash is already escaped. A user who enters the string will use the backslash as an escape character, unaware of the fact, that Qt requires a double backslash. I was trying to replace the single backslash with
string.replace("\\", "\\\\"); but that did not work.
QRegExp::escape() did not work either. By parsing the string character for character I realized the backslash is not even recognized. That is too bad. Is there a way around this?

jefftee
20th January 2015, 21:48
Qt doesn't require double backslashes, it's the C++ compiler that requires the double backslashes in quoted strings. If you are getting the string from user input or reading from a file, double backslashes are not required. This example reads the string from the file:


QFile f("/Users/jefft/test.txt");
f.open(QFile::ReadOnly);
QString str = f.readLine();
f.close();
QRegularExpression re("\\/(?<!\\\\\\/)");
QStringList strlist = str.split(re);

Where the test.txt file contains:

hello/world/how\/are/you

This should be the same if your text is coming from a QLineEdit, etc.