Global Substitutes in Vim

Global Substitutes in Vim






Note

We are no longer accepting new customers or work orders at this time. Thank you for your interest.


Let's say you've written a script, say in Perl, which takes some action which does not require generating output. But, during development, you added a lot of print statements, which you would now like to turn off. But you don't want to delete the lines; it would be nice to simply disable them in a way that they can be turned back on again later. How can you do that?

Global Substitution in Vim

One way is to utilize a powerful substitute operation in Vim text editor. This will also work in the older Vi editor as well.

We imagine that for every print statement, we'd like to surround it with an "if":

if (!$silent) { ...print statement... }

That can be done by typing the following in Vim:

:%s/^\([ \t]*\)\(print ".*\)/\1if(!$silent) { \2 }/c

Now, every line that looks like:

print "info: SN file path: $snfile\n";

Will be turned into:

if (!$silent) { print "info: SN file path: $snfile\n"; }

How Does That Work?

That Vim command looks pretty cryptic; let's break it down to see how it works.

The first character (:) puts you in line mode, so you can enter an entire command line into Vim. The command is processed when you hit ENTER.

The next character (%) means "act on all the lines in the editor". Usually you use a range of lines separated by a comma, such as "5,10", or "1,$" (meaning line 1 thru end of file). The "1,$" is used so often, they made a shorter version for it, "%" - meaning, all the lines in the editor.

The next character (s) tells what kind of operation this is. S = Substitute. Just like with sed or perl or other languages, there's going to be two sets of data separated by slashes: the thing to look for, and the thing to replace it with.

The Lefthand Side

Inside the first set of slashes is

^\([ \t]*\)\(print ".*\)

This part is a limited kind of regular expression - not perl regexp, an old-fashioned more limited kind.

The (^) character means "anchor to beginning of line", so that the following text should match only at begin of lines.

The next part is grouped with the grouping symbols \( and \). Inside there is

[ \t]*

which means "any characters that are spaces or tab characters, zero-or-more times." (note that there is a space character between the ([) and the (\) symbols, because it is one of the things we're matching at that point).

The next piece is also grouped by \( and \) symbols, and reads

print ".*

This is what we're looking for - a print statement, an opening double-quote, and every character following it (.*).

Why did we group the two sets of information we're matchine (the whitespace to the left of the print statement, and the print statement itself)? Because we want to insert something between them when we do the substitute!

The Righthand Side

Each thing we grouped on the left side has been assigned a number - 1 for the leftmost piece, 2 for the next piece. We can embed them into our replacement text, on the right side, with a backslash in front of the number (\1 or \2).

\1if(!$silent) { \2 }

Vim Substitutions from Unix Command Line

If you find yourself doing the same substitutions many times, you might want to run them from the command line. Then you can script them, or make tcsh aliases for them, whatever.

Here are some example commands that were used to transform some Electrical Engineering data into a proper format:

vim file -c '%s/\(\lt;PIN [a-z]\+\)\([0-9]\+\)/\1[\2]/' -c 'wq!'
vim file -c '%s/\(\lt;PIN.*\_.\{-}.*END [a-z]\+\)\([0-9]\+\)\$/\1[\2]/' -c 'wq!'

Sample data - before:

PIN idin0
  DIRECTION input ;
  PORT
    LAYER metal4 ;
    RECT 0.0 1.86 0.24 1.98 ;
  END
END idin0

Sample data - after:

PIN idin[0]
  DIRECTION input ;
  PORT
    LAYER metal4 ;
    RECT 0.0 1.86 0.24 1.98 ;
  END
END idin[0]

To truly follow those macros, you should read the Vim manual.

General Rule of Thumb

With Vim, in command mode, if any character has special meaning (like /, [, ]), escaping it (putting a backslash before it) removes the specialness of the character.

But the opposite is also true - some characters have no special meaning (like parentheses) on the left hand side, and must be escaped to have their special meaning.

Books and Docs

You can read the Vim User Guide on the web.

The Vim 5.6 Reference Guide is also online in PDF format.

O'Reilly's basic Vi book is Learning the vi and Vim Editors.

They also have their VI Editor Pocket Reference booklet that's easy to carry around.

Conclusion

If you're a seasoned Vi/Vim user, you probably already know this. If you haven't used it for a while, hopefully this has been a nice refresher for you.

While most Windows users are struggling to edit 200 lines by hand, making the same changes over and over, you can be on your way after a global-substitute does all the heavy lifting for you.

And don't forget, you can download and install Gvim for Windows for free! There's no excuse not to use a nice utility like this when it fits the need.

Thanks to my friend Lucan for this Trick.



Bookmark and Share


Don't miss the latest unix tips and tricks!
Subscribe to our low-volume mailing list:

Privacy Policy

See other tricks:  Web/PHP | Unix/Linux | Perl | SQL | General


Sample Sites | Customers | Our Team | Contact Us | Tips and Tricks | Tools | Our Network | Home

Copyright © 2006 - 2010 Keith Smith Internet Marketing LLC, all rights reserved.
Problem with this web site? please let us know