Search code examples
regexreplacepcre

Replace last occurences of string in lines between two strings


I'm trying to build a regex that would enable me to replace the last comma on multiple lines between two specific strings.

Sample text:

BEGIN_MESSAGE_MAP(SomeForm, BaseForm)
    ON_COMMAND(CID_ButtonAction, OnButtonAction)
    ON_NOTIFY_EX(CID_Notify, 0, OnNotify)
END_MESSAGE_MAP()

Desired output:

BEGIN_MESSAGE_MAP(SomeForm, BaseForm)
    ON_COMMAND(CID_ButtonAction, &ThisClass::OnButtonAction)
    ON_NOTIFY_EX(CID_Notify, 0, &ThisClass::OnNotify)
END_MESSAGE_MAP()

Replacing the last comma on a line is easy enough:

find (,)([^,]*?)$

and replace with (?1,&ThisClass\:\:\2).

I was also able to build a regex that matches everything between BEGIN_MESSAGE_MAP and END_MESSAGE_MAP.

(?<=BEGIN_MESSAGE_MAP)(.*\R)*(?=END_MESSAGE_MAP)

The question is - how do I put these two together so that I can only replace between these two strings?


Solution

  • You can search using this regex:

    (?:^\h*BEGIN_MESSAGE_MAP|(?!\A)\G)(?:.*\R)+?.*\K(,\h*)(?=(?:.*\R)+^END_MESSAGE_MAP)
    

    And replace it by:

    $1&ThisClass::
    

    RegEx Demo

    RegEx Details:

    • \G asserts position at the end of the previous match or the start of the string for the first match. By placing negative lookahead (?!\A) we make sure that \G doesn't match at the start of the string.
    • \K resets the starting point of the reported match.
    • Lookahead condition in the end (?=...) is to make sure that we have END_MESSAGE_MAP ahead of us.