I have a code where a QString is being modified using a regular expression:
QString str; // str is the string that shall be modified
QString pattern, after; // pattern and after are parameters provided as arguments
str.replace(QRegularExpression(pattern), after);
Whenever I need to append something to the end of the string I use the arguments:
QString pattern("$");
QString after("ending");
Now I have a case where the same pattern is being applied two times, but it shall append the string only once. I expected that this should work (I assume that the initial string doesn't end on "ending"):
QString pattern("(ending)?$");
QString after("ending");
But if applied twice this pattern produces double ending: "<initial string>endingending".
Looks like the ()? expression is lazy, and it captures the expression in parentheses if I force it with a sub-expression before:
QString pattern("string(ending)?$");
QString after("ending");
QString str("Init string");
str.replace(QRegularExpression(pattern), after);
// str == "Init ending"
What's wrong with the "()?" construction (why it is lazy) and how to achieve my goal?
I'm using Qt 5.14.0 (due to some dependencies I cannot use Qt6).
A pattern like
(foo)?$matches twice at the end of a string ending withfoo. You can see easily in action in Perl or https://regex101.com/r/3Oqwo1/1 :Therefore you'll do two substitutions at the end, neglecting your purpose.
(A way to see this is that patterns match between characters:
If the "tail" is fixed-length, you can use a negative lookbehind, like already suggested:
(?<!foo)$.Note that there's no
.*before, nor?after the negative lookbehind. If you add them, you'll again break the matching:Global matching will happen twice in
abcfie, once matching the entire string, and again matching the empty string at the end (look at the offsets). This will result in 2 replacements.This will match at the very end of the string, resulting in a replacement that you don't want (string already ends in
foo).