Search code examples
regexvim

Escaping back-references in recursive search


Is it possible to back-reference the result of an outer :g command in a recursive call (or an inner :s call?)

For instance, let's say I want to search for something above the cursor, and modify it when it appears below the cursor:

:1,.g/Hello, \(\w\+\)!/.,$s/\1/\1-San

This should replace:

Hello, Luciano!

Goodbye, Luciano!

with

Hello, Luciano!

Goodbye, Luciano-San!

If you place the cursor on the empty line.

However, it complains about an invalid back-reference. This is in reference to the last \1 (note that , maybe surprisingly the first \1 in the search pattern -but not the replacement - works!). The reason is likely that the :s expression does not have any capture groups.

So my question is, whether there is a way to 'escape' the inner context of the command to execute in :g to be able to back-reference a match group from the outer g?

(I appreciate there are other ways to achieve the desired effect in the above contrived example - but my question relates specifically to escaping back references, not writing a better regex - the example here is just for illustration)


Solution

  • Back references can be used within a search pattern:

    before: xoxoxo foobarfoo xoxoxo
    
    /\(foo\)bar\1
    
    after: xoxoxo foobarfoo xoxoxo
                  ^^^^^^^^^
    

    as well as in the replacement part of a substitution:

    before: xoxoxo foobarfoo xoxoxo
    
    :s/\(foo\)bar\1/baz\1baz
    
    after: xoxoxo bazfoobaz xoxoxo
    

    This is possible because the capture group and the back reference occupy the same "pattern space" in a single atomic "command".

    When you do :g/<pattern>/<cmd>, <cmd> is a separate "command" that doesn't share :g's "pattern space" so it is impossible to reference a capture group from <pattern> in <cmd>.

    What is possible, though, is to reuse <pattern> in <cmd>:

    :g/\(foo\)bar\1/s//baz\1baz
    

    but you are still not referencing a capture group from :g in :s even if it looks like it. You are making a new search with the same pattern and referencing the capture group in that new search.