How do I search and replace text in Neovim
Searching and replacing text is something a developer would do frequently. Unlike other editors such as Visual Studio Code, Neovim doesn’t come with a search box for you to search and replace text in a file or in a workspace, and it has it own unique mechanism. In this post I want to share how do I search and replace text efficiently in Neovim.
Searching and replacing text in a buffer with :substitute
command
Searching and replacing text in Neovim is a bit different from what you might be used to in other editors. Instead of a search box, you use the powerful :substitute
command, which gives you fine-grained control over your replacements.
To replace all occurrences of foo
with bar
in the entire file, you can use:
:%s/foo/bar/g
:%
means the whole file.s
stands for substitute./foo/bar/
is the pattern and replacement.g
means “global”—replace all matches on each line.
If you only want to replace in a specific range, say lines 10 to 20:
:10,20s/foo/bar/g
Sometimes, you want to confirm each replacement before it happens. Add the c
flag:
:%s/foo/bar/gc
Neovim will prompt you for each match, letting you decide whether to replace it.
You can also ignore cases by adding the i
flag:
:%s/foo/bar/gci
Searching and replacing text in a buffer with gn
motion
While the :substitute
command is powerful, sometimes you want a more interactive way to search and replace text—especially when you only want to change some matches, not all. That’s where the gn
motion comes in.
The workflow is simple:
- Search for the text you want to replace using
/pattern
or*
. - Use
n
to jump to the next match. - Use
cgn
to change the current match. Type your replacement, then hit<Esc>
. - Use
n
orN
to jump to the next or previous match. - Hit
.
(dot) to repeat the last change on the next match.
For example, to replace foo
with bar
interactively:
/foo
n
cgnbar<Esc>
n
.
n
n " skip the previous match and don't change it
.
This lets you skip matches you don’t want to change, and quickly apply the same edit to others. You can also use other operators with gn
, such as dgn
to delete matches, or ygn
to yank them.
What’s great about this approach is that the change becomes repeatable with the dot command, making it much faster than running :substitute
with confirmation for every match.
Searching and replacing text across buffers with Quickfix list
Sometimes you need to search and replace text across multiple files or buffers. Neovim makes this possible with the Quickfix list and the powerful :cdo
and :cfdo
commands.
Insert buffers into Quickfix list with :grep
command
One classic way to batch search and replace is to use the built-in :grep
command to populate the Quickfix list. This approach is simple and works out of the box.
To search for foo
in all .js
files and load the results into the Quickfix list:
:grep foo **/*.js
:copen
This will open the Quickfix window with all matches. You can then use :cdo
to run a substitute command on every matching line:
:cdo s/foo/bar/gc
Or use :cfdo
to run a command on every buffer in the list:
:cfdo %s/foo/bar/gc
Insert buffers into Quickfix list with picker of snacks.nvim
If you prefer a more interactive workflow, modern Neovim plugins like snacks.nvim
let you use fuzzy pickers to select files and load them into the Quickfix list. This is my favourite way to batch search and replace, as it gives you full control over which files to operate on.
For example, you can use the grep
picker from snacks.nvim
to search for a pattern, select the files you want, and send them to the Quickfix list. Once the list is populated, you can use the same :cdo
or :cfdo
commands as above.
This workflow also works with other pickers like Telescope or fzf-lua. The flexibility to preview and select files before running replacements makes it much safer and more efficient.