Vim Search, Find and Replace: Basic and Advanced Commands

vim-search-highlight

Can a developer live without a good search engine in his editor or IDE? What developer never used the famous find and replace in multiple files?

Yep. Nobody.

You can be happy though, dear Vim user: your editor totally shine by its search features! With a minimum of configuration you can be able to search whatever you want, wherever you want at light speed.

You need to use Vim to find and replace occurrences in thousand of files and filter with a maximum of granularity? This article will teach you the “how” if you are ready to learn it.

A little precision: I will often refer to Vim current working directory in this article. To know what directory it is for you, execute in Vim the ex command :pwd. To change it, you can use :cd mydirectory.

Enough small talk. Let’s dive in!

Search and replace in vanilla Vim

Learning vanilla Vim capabilities without trying plugins at first allow you to be efficient regardless of Vim’s configuration.

Being efficient in Vim without your precious vimrc is priceless. Specially when you are lost on a remote server trying to fix-quickly-this-wrong-configuration-which-crash-the-whole-thing.

Vim search in the current file

The basics

In order to search in the current open file, you just need to type / in normal mode. Then you need to type your search pattern and the result become highlighted in your file.

To go back and forth through the results, you can type n to go forward in the file and N to go backward.

Using / will search forward in the file. If you need to directly search backward, you can use ? instead.

Setting the search highlights

It is very practical to see the search highlighted in the file. However in Vim it’s not activated by default. To activate it, you can type :set hlsearch or set it in your vimrc.

If you use Neovim, the highlighting is set by default.

Clearing the last search highlight

The command :noh in normal mode will clear this highlight you tried to get rid off by trying (almost) every button on your keyboard.

Since you don’t really want to type this command each time you do a search (we are all lazy here), you can map a key to the command in your vimrc as follow: map <esc> :noh<cr>.

Each time you will type esc, you will clear the last search highlighted and therefore keep your sanity. Lucky you.

Searching the word under the cursor

  1. Place your cursor on the word you want to search
  2. Type * o g*.

As with /, every results will be highlighted.

To search for partial words (include word parts in the results), you can use the keystroke g*.

Vim search case insensitive

  1. /search\c - Search with case insensitive
  2. /search\C - Search with case sensitive

You can as well write the following command in your vimrc:

  • set ignorecase - All your searches will be case insensitive
  • set smartcase - Your search will be case sensitive if it contains an uppercase letter

Be aware that ignorecase needs to be set for smartcase to be set as well.

Vim search in multiple files

vimgrep

vimgrep quickfix window The quickfix window after executing vimgrep kernel **/*.php and :copen

Searching with vimgrep will populate the quickfix list (see :help quickfix and :help quickfix-window in Vim) with the result of the search.

It implies that you need to use the command :cnext and :cprev to go through the results (instead of n and N respectively).

You can as well open the quickfix window with :copen and go through the results.

For example:

  • :vimgrep pattern * will search in every files of the working directory the word “pattern”.
  • :vimgrep pattern a.txt b.txt c.txt will search the same word only in the files a.txt, b.txt and c.txt.
  • :vimgrep pattern *.php will search “pattern” in every php files
  • :vimgrep pattern **/*.php will search “pattern” in every php files in the working directory and every subdirectories

Quick tip: since the command @: repeat your last command, you can go through all your results by taping :cnext and then only using the @: keystroke.

For more information about vimgrep, I strongly advice you to look at the excellent vimcast about it.

Last but not least: you should read Vim’s help about vimgrep by typing :help vimgrep.

Vim search using the command grep

Vimgrep is good but unfortunately pretty slow. As an alternative you can use the external program grep directly in Vim. Obviously you need grep to be installed on your machine.

Using grep and vimgrep is similar. For example:

  • :grep mySearch * will search every occurences of mySearch in the working directory
  • :grep mySearch a.txt b.txt c.txt will search every occurences of mySearch in the files a.txt, b.txt, c.txt

I won’t cover here every use of grep. You can read more about it in the official grep manual. For its use in Vim you can type in Vim :help grep.

Vim find and replace

Vim substitute in the current file

Vim has a very powerful find and replace functionality thanks to the substitute command.

Let’s look at some examples:

  • :s/pattern/replace/g change each “pattern” by “replace” on the current line
  • :%s/pattern/replace/g change each “pattern” by “replace” in the current file
  • :%s//replace/g change your last search by “replace” in the current file

You may ask: what the hell those letters and signs mean? You’re curious, I like that.

  • The letter s stands for substitute
  • The keyword % will target the entire file instead of the current line.
  • The keyword g means “global” - more than one occurrences are targeted

Those are the most common substitute command you will use. Nevertheless I encourage you to consult Vim’s help (again?) by typing :help substitute.

Note that the substitute command can be grandly enhanced by the excellent Tim Pope’s vim-abolish plugin. A must have for every cool Vim users out there!

And I know you’re cool.

vim substitute This substitute will crash Symfony 4 kernel

Vim find and replace one occurrence at a time

It’s very simple to search and then decide if you want to keep or replace each result in a file:

  1. Execute a regular search like /pattern
  2. Use the keystroke cgn on the first result to replace it
  3. Type n or N to go to the next result
  4. Use . to replace the occurrence with the same replacement (or go to the next result if you want to keep it)

What is this cgn keystroke you may ask? What does it mean? If you read :help gn you will see that gn is the same as n but will as well start Visual mode and select the occurrence. We just do a change (c) on the next (selected) search occurrence. From there you can can easily understand that things like cgN or dgn will work as well.

With this simple technique you can do a granular find and replace in the whole file.

Vim find and replace in files

You can use the excellent Vim arglist to do so. Think of it as an internal list of files you can populate and modify.

If you want to replace an occurrence in every html and twig files, you can type the following:

  1. :arg *.html - Empty the buffer and populate the arglist with all html file in the current working directory
  2. :argadd *.twig - Add twig files to the arglist
  3. :argdo %s/pattern/replace/ge | update - Replace the occurence pattern by replace in every files of the arglist

At that point you may scream to your screen, shacked violently by curiosity: what means e at the end of the substitute command? It simply prevent Vim to display an error message when the pattern is not found in a file.

What about doing a find and replace for the files in the working directory and subdirectories? You need to populate the arglist as follow:

  • :arg **/*.html
  • :argadd **/*.php

You need to find and replace in the open buffer? Well, it’s easy. I expected you to have more difficult questions. Simply execute:

:bufdo %s/pattern/replace/ge | update

Do you know what I encourage you to read? Yes: :help arglist!

Vim search with external plugins

I have a good new: there are better alternatives for vimgrep, grep or using the arglist to find and replace in files. The plugins described here will change your search life!

Be aware: I won’t cover every search plugins available. There are simply too many and I ’m too lazy for that. However I will give you the most powerful combo for any of your search needs.

That’s all we want, isn’t it?

Since we speak about Vim plugins, I wrote another article which list the necessary Vim plugins to build a Vim PHP IDE. In case you’re interested.

One Plugin to rule them all, One Plugin to find them

If there was one plugin I would take with me on a lost inhabited island (with a computer and Vim) it would be fzf.vim coupled with the command line fuzzy finder fzf. This is a must have. I beg you to try it and here’s why:

  • It’s blazing fast (written in Go). Einstein was wrong: you can go beyond light speed
  • It allows you to search in your terminal whatever file or history entry you want
  • It can be coupled with Vim to search a lot of useful things like buffers, open files history…

Here some basic examples:

  • :Files - Search a file in your working directory and subdirectories
  • :Buffers - Search a file open in one of your buffer
  • :History - Search a file in your open file history

Simple and highly configurable!

Vim search in multiple files with Ripgrep

fzf is a powerful tool but it’s not enough to search a precise occurrence in a whole bunch of files. You need another crazy fast terminal program: ripgrep.

Ripgrep coupled with fzf will bring under your little fingers the best search engine I’ve ever seen in any IDE. No more, no less.

In order to link fzf with ripgrep, you can look to my fzf config file on github.

Then you just have to enter the command :Rg pattern to search “pattern” in every files of the working directory. Mind blowing.

fzf and ripgrep The sweet combo fzf / ripgrep

You can use as well ripgrep instead of grep for the :grep command.

Vim find and replace in multiple files with Vim ferret

The last plugin I use is ferret. It allows you to search an occurrence in multiple files, select what results you want to replace and finally replace them.

Moreover if you have ripgrep installed on your system, this plugin will use it by default!

  • :Ack pattern will search in the working directory
  • :Ack pattern /path/to/directory will search in the specified path and its subdirectories

At that point Ferret will populate the quickfix window with every results found. You can delete the result by typing dd in case you don’t want to replace it. You can as well type enter to open the file with the result highlighted.

Then typing :Acks /pattern/replacement/ will replace every results still present in the quickfix window.

Simple, granular, powerful: that’s what we want!

Vim is now a search-killing-machine

This overview will bring you whatever search functionality you need as a developer.

I personally use built-in vim search functionality when I search (or search in replace) in one file. When the search operation needs to be in a whole project or on multiple files, I use fzf, ripgrep and ferret.

If you know other functionalities / plugins which can bring even more coolness in our life, please don’t hesitate to let a comment!

You know, sharing is caring.

vim search love