Substitution in Vim

I’m getting to grips with Vim now, using it almost on a daily basis for as a JavaScript editor at Mozilla. One thing that I figured out today was how to do optional text substitution on a range of lines.

Text substitution in Vim is pretty easy using the ‘:substitution’ command (shortened to ‘:s’). The command accepts regular expressions, but can easily do ‘normal’ text replacement. It’s formatted like this:

:<RANGE>s/<BEFORE>/<AFTER>/<FLAGS>

<RANGE> is the range of effect you want the command to have, <BEFORE> is the word you’re searching for, <AFTER> is the word you want it replaced with and <FLAGS> are various flags which affect how the command works.

Let’s first look at flags.

Given the sentence: “I love giant killer robots and giant monsters. Giant Robots are the best.”

A simple substitution looks like this ‘:s/giant/massive/’ and when executed will change the first instance of the word ‘giant’ with the word ‘massive’.

The first flag I want to introduce is ‘g’, which will tells the command to execute across the entire sentence, not just the first match. So ‘:s/giant/massive/g’ will change the sentence above to “I love massive killer robots and massive monsters. Giant Robots are the best.”. Notice how the ‘Giant’ hasn’t been replaced – that’s because as standard we match in a case sensitive manner.

The next flag is the ‘i’, which will change from case sensitive pattern matching, which is the default, to case insensitive. The command ‘:s/giant/massive/gi’ will change the sentence to “I love massive killer robots and massive monsters. massive Robots are the best.”

Adding the ‘c’ flag will prompt you to confirm each substitution.

The range is where it gets interesting, and if I’m correct I think these range specifications will work on lots of Vim commands.

To execute a command on a range of lines you can simply add the line numbers before the command to execute, with a comma between the two. so ‘:10,20s/giant/massive/g’ will execute that command on lines between 10 and 20.

Vim comes with various non-numeric markers which you can use for the range.For example ‘.’ which refers to the current line and ‘$’ which refers to the end of the file. These can be mixed and matched as you see fit, so to specify between line 20 and the end of the file, my range would be ’20,$’. Vim will automatically assume that if you miss out one of the range values, you mean the current line, ‘.’. So a range of ‘., $’, from the current line to the end of the file, is the same as ‘,$’.

You may see the % marker preceding a command, which is a Vim shortcut for ‘1,$’ – beginning to end, or the entire file. ‘:%s/giant/massive/g’ will substitute every instance of ‘giant’ for ‘massive’ across the file you’re looking at.

If you want to specify a number of lines from where you are, you can use the ‘+’ sign – so ‘.+15’ means for the next 15 lines. As above, the ‘.’ is assumed, so this can be shortened to just ‘+15’.

So with that all in mind, to substitute text from the current line for the next 15 lines, asking for confirmation, you’d want to write something like ‘:,+15s/giant/massive/gc’

As ever http://vim.wikia.com/wiki/Search_and_replace is a great place to look at for help

Leave a Reply