Replace All Occurrences of a Word in Vim and Neovim

Jun 19, 2023
We've all faced this problem! It's probably one of the most how-to do y in vim things I have Googled, so here's how I made it simple.

To start with, this is about replacing all occurrences of a word in a single buffer, not in multiple buffers or in the whole project - I will write about the latter in a later post.

As is always the case, there are multiple ways to do this, but I will focus on one that I use and has been most appropriate for me - search and replace by substitution!

You Vim masters are already saying "Aaah, I know that", but hold on, I am going to show you how I extended that into a function and wrapped it in a keymap - now my replace all is quick, easy and convenient, I'll show you how.

Step by step, for everyone :)

To search and replace in vim, by substitution, you first enter command mode by pressing : in normal mode, followed by % to let you access all current file contents, then s to denote substitution, then a forward slash, your search string, another forward slash, your new word, yet another forward slash then a few other letters for the extras, eg c for confirmation, i for ignoring the case, and g to replace all occurrences, then you finally press enter and your old word is replaced with the new word!

Quite a plethora of steps, right. And that's what I wanted to change - make the above steps as fast and brainless as possible.

In summary, this is what you would type in normal mode and press enter:

:%s/old/new/g

This is what I used, and I reckon many use the same too - takes a couple of seconds at best, and a few things to keep in your memory.

The first step to make the above faster is to map the above to a key map, so you will just need to press a few keystrokes and it'll go into command mode and prefix the `%s/` for you. Then the next step is have it paste the old word for you into that prompt, so you do not have to type it all over again.

Then, if you're like me, at most times you do not want to change the entire word, but likely just a section of it, eg I usually find myself just changing attrs to attributes, and it tires me to type the whole word, not just into the search phrase, but also into the replace section, just a lot of work especially if you do this repeatedly and for long words/phrases.

So I made the following function to make it all easy! I use Lua on Neovim, but I'll rewrite the same in Vimscript for our Vim people :)

    ["lr"] = {
      function()
        local old_word = vim.fn.expand "<cword>"
        local new_word = vim.fn.input("Replace " .. old_word .. " by? ", old_word)
        
        if new_word ~= old_word and new_word ~= "" then
          vim.cmd(":%s/\\<" .. old_word .. "\\>/" .. new_word .. "/g")
        end
      end,
    },

I'll explain what each line does:

  • lr is my keymap - in normal mode, I just need to navigate to the word I need to replace, type lr and it calls the defined function. You can map this to anything you want.
  • Then in the function, we retrieve the word under the cursor using the Vim function expand() with the <cword> argument. Then assign the value to the old_word variable
  • We then prompt the user to enter a new word to replace the old_word. I used the input() Vim function to display a prompt with the message "Replace <old_word> by? " and set the initial input value as old_word. The user's input is assigned to the new_word variable. If you do not want to set the initial input value, the just remove the old_word second argument in the input function. For me having it is so powerful as I can edit it to what I want since in most cases my new_word will closely resemble the old_word!
  • We then check if the new_word is different from the old_word and it is not an empty string. This condition ensures that the replacement will only occur if the user entered a new word and it is different from the original word - spicy isn't it :)
  • Then finally, we use the vim.cmd() function to execute the Vim substitution command. The command :%s/\<old_word\>/new_word/g performs a global substitution within the entire file (%) for the exact whole word old_word and replaces it with new_word. The \< and \> are used to match the exact word boundaries. The g flag ensures that all occurrences of old_word are replaced, not just the first one.
  • Press enter and see magic!

And that's it chaps!

In Vimscript, something like this should work

function! ReplaceWord()
  let old_word = expand('<cword>')
  let new_word = input("Replace " . old_word . " by? ", old_word)
  
  if new_word !=# old_word && new_word != ''
    execute "%s/\<" . old_word . "\>/" . new_word . "/g"
  endif
endfunction

nnoremap <silent> lr :call ReplaceWord()<CR>


Let me know if this search and replace solution worked for you, or you improved it, or you have totally new way of doing the same thing?

Happy Vimming. 
6
12
968
Mohit · 3 months

This is super helpful!

Mohit Marathe · 3 months

This is super helpful!

Mohit Marathe · 3 months

This is super helpful!

Mohit Marathe · 3 months

This is super helpful!

Mohit Marathe · 3 months

This is super helpful!

GiSmo · 6 months

Thanks a lot ^^