Unexpected RegEx behavior in Delphi XE
delphi, delphi-xe, regex
Solution
You need to escape the `\` characters in your replacement string:
ReplaceWith = '{\\*\\bkmkstart BM0}\\plain\\f0\\fs24\\cf0 ^{\\*\\bkmkend BM0}\\plain\\f0\\fs24\\cf0 \\cell}';
When you make this change the output is:
{\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^{\*\bkmkend BM0}\plain\f0\fs24\cf0 \cell}
In fact, for your replacement string, you only need to escape the backslash in \f0 which, as it happens, appears twice. Personally I think it's just easier to escape the backslash indiscriminately.
By combining regular expressions and RTF you've mixed your own special backslash soup — tread carefully. Just be thankful you aren't using C or older versions of C++ that do not support raw strings. That backslash soup would be completely unpalatable!
Problem
Delphi XE, using Delphi's own RegularExpressions unit. I'm attempting to correct some bad RTF code, where 'bookmark' tags cross the boundaries of a table cell. Seems simple enough. The code I'm using is below. Here's the general idea. Given this text ``` {\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^\cell} ``` Look for a match to this pattern (there should be exactly one in the given text): ``` {\\\*\\bkmkstart BM0}\\plain\\f[0-9]\\fs[0-9]+\\cf[0-9] \^\\cell} ``` When found, replace it with this (non-RegEx) string: ``` {\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^{\*\bkmkend BM0}\plain\f0\fs24\cf0 \cell} ``` The expected results are that the first string should be replaced with the last string, eg: ``` {\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^\cell} *becomes* {\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^{\*\bkmkend BM0}\plain\f0\fs24\cf0 \cell} ``` However, the result I'm actually getting is this: ``` {\*\bkmkstart BM0}\plain{\*\bkmkstart bm0}\plain\f0\fs24\cf0 ^\cell}\fs24\cf0 ^{\*\bkmkend BM0}\plain{\*\bkmkstart bm0}\plain\f0\fs24\cf0 ^\cell}\fs24\cf0 \cell} ``` It looks as if the RegEx parser is getting horribly confused somehow, but I can't even characterize what is happening. It's not a mere double replacement, or an insertion instead of replacement. The 'ReplaceWith' string does seem to be the source of the confusion, though. If I use a nice simple 'XXXX' for the ReplaceWith string, instead of the RTF, it works exactly as it should. So, any ideas how/why the RegEx search/replace is breaking so strangely here? Here is the code I'm using: ``` procedure TfrmMain.btnProcessClick(Sender: TObject); const SourceString = '{\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^\cell}'; RegExFind = '{\\\*\\bkmkstart BM0}\\plain\\f[0-9]\\fs[0-9]+\\cf[0-9] \^\\cell}'; ReplaceWith = '{\*\bkmkstart BM0}\plain\f0\fs24\cf0 ^{\*\bkmkend BM0}\plain\f0\fs24\cf0 \cell}'; var ResultStr: string; MyRegEx: TRegEx; begin MyRegEx := TRegEx.Create (RegExFind); ResultStr := MyRegEx.Replace (SourceString, ReplaceWith); ShowMessage (ResultStr); end; ```