Find and Replace in Neovim

While Neovim may not be my daily editor, I still prefer it to modify files quickly. Often I find myself in Neovim when I need to make small changes to JSON or YAML files. A common action that I perform is a simple "find and replace" which is supported by most editors. As with most things, the method to do this in Vim is powerful, but not necessarily straightforward unless you know the right commands and flags. In this post, I'll go into some detail about substituting characters in Vim and Neovim.

Aaron Bos | Monday, March 25, 2024


Simple Find and Replace

If you've landed on this post looking for a quick solution, I won't make you scroll. Below is a command that you can use in Neovim (and Vim) to find a string "Waldo" and replace all occurrences with another string "Wizard Whitebeard".

Where is Waldo? Have you seen Waldo?
There you are Waldo.

:%s/Waldo/Wizard Whitebeard/g

I'll go into more detail on the command structure and flags below, but :%s invokes the substitution command. Waldo is the string that we are looking for and Wizard Whitebeard is the string to replace occurrences of Waldo with.

The /g is required to replace instances of the string on the same line. Without /g the Waldo in "Have you seen Waldo?" would not be replaced because it is the second occurrence of the string on that line.

If you're interested in learning a little bit more about the :substitution command, grab a coffee and read on.

Command Breakdown

As I mentioned, the feature of Neovim (and Vim) that we are concerned with here is substitution. Substitution refers to the ability to perform string replacements on a whole range of lines.

The command to invoke substitution is :substitution or :s as we saw in the previous example. Those with a keen memory may be wondering why we used :%s in the previous command. The reason for the % range prefix is used to indicate that the command should be applied to all lines instead of just the current line. This means that we can also use the % with :substitution as well. So :%substitution is the same as :%s and for the remainder of this post I'll use :%s to save some keystrokes 😎.

Now that we know what command we're concerned with we can focus on the actual syntactical structure. Generally the substitution command is constructed as follows.

:[range]s/<string-to-find>/<string-to-replace>/[flags]

If we were to compare this structure to our previous example then we can make the following mappings.

  • range: %
  • string-to-find: Waldo
  • string-to-replace: Wizard Whitebeard
  • flags: g

While the percent sign may be the most commonly used range for substitution, there are many other things that we can do with this range beyond considering all lines for the command. Ranges are quite robust, but beyond the scope of this particular post. If you are interested in learning more, head over to the docs here.

The one feature of ranges that I'd like to call out is to be able to grab the range for the current selection in Visual mode. This feature is great for substituting text just inside of a selection rather than all of the lines or a hard-coded range.

To do this, simply enter Visual mode (press v while in Normal mode) and select the text you'd like to consider for substitution. Once you've selected the text, press : which should then display this in the command area.

:'<,'>

From there we can add our substitution command, which will just be applied to the text that we have selected from Visual mode.

:'<,'>s/Waldo/Wizard Whitebeard/g

I'm sure there are plenty of other patterns to apply with ranges and selections, so if you've got one reach out and let me know!

Flags

The substitution command doesn't come with too many flags and we've already seen the global or g flag in our previous example. The other two flags that we have available are as follows.

  • print or p: which results in the command printing out the last line it changes
  • confirm or c: which prompts the user for each substitution before applying the change

When using the confirmation flag, you'll have a few options to choose from.

  1. Make the change by pressing y.
  2. Skip changing this occurrence by pressing n.
  3. Make the change and all subsequent changes without further confirmation by pressing a.
  4. Quit without making more changes by pressing q.
  5. Make the current change, then quit by pressing l.

Let's a take look at our previous command, but include the confirmation flag.

:%s/Waldo/Wizard Whitebeard/gc

With each occurrence of the string we are presented with this prompt, allowing a decision to be made before the change takes place.

replace with Wizard Whitebeard (y/n/a/q/l/^E/^Y)?

This post only cracks the surface of what can be done with substitutions. If you're curious about learning more, I'd recommend checking out applying search patterns within the text to find or replace using the substitute command. As with most things in Vim, foundational knowledge can be composed and applied to perform powerful operations.


ShareSubscribe
As always thank you for taking the time to read this blog post!