marco
marco

Reputation: 1752

QRegularExpression: cannot make part of match optional

Given the following string:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8h/ls5JiSNQB5gAAAABJRU5ErkJggg== "this is a tooltip"

that should represent a data url of an image, I should extract all the parts of it so I made a RegEx for it:

str = "(data:(\w+)/(\w+);base64,)(.*)(\"([\w*|\s*]*)\")"

It works as with the following code:

QRegularExpressionMatch match = regex.match(str);
for(int i = 0; i <= match.lastCapturedIndex(); ++i )
    ui->outputBrowser->append(QString::number(i) + ": " + match.captured(i));

I can see:

0: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8h/ls5JiSNQB5gAAAABJRU5ErkJggg== "this is a tooltip"
1: data:image/png;base64,
2: image
3: png
4: iVBORw0KGgoAAAANSUhEUgAAAF8h/ls5JiSNQB5gAAAABJRU5ErkJggg== 
5: "this is a tooltip"
6: this is a tooltip

But if I add a ? to the end of the RegEx, it doesn't work. The "this is a tooltip" - that is optional - goes to the data part and not in a standalone part.

str = "(data:(\w+)/(\w+);base64,)(.*)(\"([\w*|\s*]*)\")?"

output:

0: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8h/ls5JiSNQB5gAAAABJRU5ErkJggg== "this is a tooltip"
1: image/png;base64,
2: image
3: png
4: iVBORw0KGgoAAAANSUhEUgAAAF8h/ls5JiSNQB5gAAAABJRU5ErkJggg== "this is a tooltip"

Where is the problem?

Upvotes: 1

Views: 337

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627056

Use the following regex:

(data:(\w+)/(\w+);base64,)([^"]*)(\"([\w\s]*)\")?
                           ^^^^^                ^

The .* is too greedy and matches every character but a newline, 0 or more occurrences. In order to be able to make the last group optional, you need to restrict this subpattern. You can do it with [^"]* negated character class.

See the regex demo

Also note that [\w*|\s*] is matching a single character that is alphanumeric or underscore (\w), a whitespace (\s), | or *. Inside a character class, | and * are literal pipe and asterisk symbols.

Upvotes: 1

Related Questions