'Using "register recall" to search and replace doesn't work when register contains newline character

I've been using the answer to Using visual selection or register for search and replace as follows:

  • v visually select
  • y yank
  • :%s/
  • Ctrl+r
  • "

This works fine in most cases. However, if newline characters are part of the visual selection I have to manually replace ^M with \n, first. What am I doing wrong?



Solution 1:[1]

What am I doing wrong?

Nothing. It's just Vim being well optimised for some workflows and not for others.

The linked thread actually contains some of the ingredients of the solution to the problem, namely that, after yanking, multiline text needs a bit of massaging if we want to use it for something else than p or P. The massaging is needed because newlines are stored as control characters in the buffer and that's what you get when you yank. But regular expressions don't really like control characters so literal ^@s must be changed into \ns and other characters must be escaped, too, like . or [, because they have a special meaning.

The solution to this problem is thus to write a function that:

  • escapes what needs to be escaped,
  • transforms newlines into \ns.

Here is one way to do it (with more intermediary steps than I would do in real life but that's better for demonstration):

function! EscapeRegister(reg)
    let raw_text     = getreg(a:reg)
    let escaped_text = escape(raw_text, '\/.*$^~[]')
    return substitute(escaped_text, "\n", '\\n', "g")
endfunction

which you would use like so:

v<motion>
y
:%s/
<C-r>=EscapeRegister(e)<CR>
/foo/g
<CR>

Feel free to call your function ER() or whatever for saving typing.

See :help getreg(), :help escape(), :help substiute(), :help @=.

The function above is fairly low-level and could be composed with other things to make higher-level tools that, for example, could handle everything in the macro above in a couple of keystrokes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1