Search code examples
qtregex-negationqregularexpression

QRegularExpression: skip matching escaped tokens


I'm replacing a QString using QRegularExpression but I have a problem with escaped tokens.

For example: a "{aaa}" in the string should be replace with a "bbb" but a "\{aaa}" should be ignored and a "{aaa}" will be set (without the "\").

eg:

this is a test called {aaa} -> this is a test called bbb
this is a test called \{aaa} -> this is a test called {aaa}

I'm using

QString& replace(const QRegularExpression& re, const QString& after);

but I cannot find a way to skip an escaped match. I guess with a negative look-behind, but how?


Solution

  • The pattern you came up with - (?<!\\){aaa} - will not match valid {aaa} that is preceded with a valid escaped backslash, \\{aaa}, see this demo.

    What you need is a regex that will account for these escaped backslashes:

    (?<!\\)(?:\\{2})*\K{aaa}
    

    See the regex demo.

    Details:

    • (?<!\\) - a negative lookbehind failing the match if there is a \ immediately to the left of the current location
    • (?:\\{2})* - zero or more occurrences of double backslash
    • \K - match reset operator discarding the text matched so far
    • {aaa} - a literal {aaa} substring.

    In Qt, string literals may contain escape sequences, \n for a newline, \r for a carriage return, etc. To define a literal backslash (that is used to form regex escapes, regex operators, shorthand character classes), you need to double the backslash:

    QRegularExpression re("(?<!\\\\)(?:\\\\{2})*\\K{aaa}")