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
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 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 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-lookingacross all files in our arguments list.
... | update: will save each file after the
:%scommand has finished running.
From inside of Vim
With the release of Vim 7.4.858 we got two new commands:
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
:clist to look at the files manually.
Now, for the fun part! We can use the same command as we did when replacing
argdo from the shell, but using
:cfdo instead of
We are opting to use
:cfdo instead of
:cdo for the fact that
run a set of commands over each element in the quickfix list, while,
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.
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.