Vim truly excels at editing text, but some common text-editing tasks are more daunting than others to do from our favorite text editor. Today, we are going to cover the various ways you can search and replace bits of text, in your shell and beyond to Vim.
From the shell
From our dotfiles you can find a script named replace, which takes three arguments - the word you want to replace, its replacement, and the pattern for where you want to replace within. Easy, right?
% replace ugly funny-looking **/*.txt
If you do not want to install yet another script to your dotfiles, you can use
sed(1)
, which is used under the hood by replace.
% git grep -l ugly | xargs sed -i "" "s/ugly/funny-looking/g"
For an extended overview on sed(1)
and replacing text in your shell, I suggest
reading sed 102: Replace In-Place.
Using Vim, from the shell
As you might be aware, Vim lets you search and replace by running:
:s/ugly/funny-looking
. The :s
there comes from sed(1)
which we used above.
We are going to use the :%s
version to search and replace across a buffer,
which is what %
means in Vim-land. So, how can we leverage that do
search-and-replace over a set of files? Enter :argdo
.
:argdo
lets us run a given set of commands over our arguments list. What is
the arguments list you might ask?
Take any directory, much like this one:
% ls
a.txt b.txt c.txt
% vim +args *.txt
We are greeted with the response:
[a.txt] b.txt c.txt
That means that our arguments list is populated with the three files listed above.
Now, with that new-found knowledge - let us see how we can search and replace over that set of files.
% vim $(grep -l ugly -r *) +"argdo %s/ugly/funny-looking/g | update"
That command is a bit of a mouthful, but do not fret. We will break it down bit by bit.
$(grep -l ugly)
: returns all files that contain the word “ugly”.+"argdo %s/ugly/funny-looking/g"
: will run%s/ugly/funny-looking
across all files in our arguments list.... | update
: will save each file after the:%s
command has finished running.
From inside of Vim
With the release of Vim 7.4.858 we got two new commands: :cdo
and :cfdo
.
They work similarly to :argdo
, but they operate over the quickfix list instead
of the arguments list.
The quickfix list is populated when you run commands such as :grep
. Which is
great, because that is how I find my way around text documents.
First of all, we need a list of files to modify. From inside of Vim:
:grep ugly -r **/*.txt
That will populate our quickfix list with a list of files. You can use :copen
or
:clist
to look at the files manually.
Now, for the fun part! We can use the same command as we did when replacing
using argdo
from the shell, but using :cfdo
instead of argdo
.
We are opting to use :cfdo
instead of :cdo
for the fact that :cdo
will
run a set of commands over each element in the quickfix list, while, :cfdo
will run it over each file in the quickfix list. Therefore, we will not run the
same command twice.
:cfdo %s/ugly/funny-looking/g | update
Voilà, we have now replaced all occurrences of “ugly” with “funny-looking” from the inside our favorite text editor.
Conclusion
With this newfound knowledge, we can now search and replace with ease using Vim’s various lists. The lists can be used for other tasks, as versatile as they are. I’m going to leave it as an exercise to the reader to find other use cases for them.