Firstly, I'd like to thank everybody who mailed me about my last vi tutorial
for their kind words - and for asking for more!
I also want to clarify that I am not using vi itself but the better known
clone called 'vim' which has been ported to a number of different operating
systems (Linux, Beos, VMS, DOS, Windows and Amiga to name but a few) and is
available for download at the vim website, www.vim.org. I'm mentioning this
because there is a chance that I might accidentally describe some vim specific
functionality and would greatly appreciate it if corrections were emailed to
me. Anyways, time to get on with it...
Lines.
There is one mildly annoying thing about vi, which is that for the most part
you don't know for certain if one line of text is displayed as just one line or
whether it might be so long as to wrap around and be displayed on the screen as
being two or more lines. This can be extremely annoying if for example you
delete four lines and, due to word wrap, you really only should have deleted
two.
For this reason it would be rather nice to know where the lines end and how to
do something about it.
Doing the first is quite simple - type :set list to see where the lines end
(which will be indicated with dollar signs, tabs indicated with '^I') and
:set nolist to get the display back to normal.
Getting vi to do something about it preemptively is rather simple too. All that
you need do is type :set wrapmargin=1 to make vi force lines not to wrap, this
is a really useful command which probably should be included in your .exrc
file.
If for some reason you want to undo this, just type :set wrapmargin=0.
You could also use :set wrap and :set nowrap for turning wordwrap on and off.
Seek and Find.
One thing that I was asked to cover was searching for text - and replacing it.
On the face of it, searching for text is fairly simple. Press / then type in
the text that you want found, pressing return afterwards. To find the next
occurrance of the same text just press / and return again.
Using / means that the search text will be looked for further into the file
that you are editing - if you want vi to search in the other direction then use
the question mark (and again you can use ? followed by the return key to search
for the previous occurrance of the text you are searching for).
If you are alternating between forward and reverse searches you don't have to
specify the search text a second time.
For example, let's say you were looking for the word 'spam' and you
accidentally hit / and the return key before you can read anything else and are
shown the next occurrance of 'spam'. You don't have to type ?spam - ? on it's
own will suffice. You can also use 'n' and 'N' for searching in the same direction and the alternate.
There's one particular disadvantage/annoyance about this though. If you look
for the word 'to' vi will find it all over the place as a portion of longer
words (try looking for 'to' in "Going towards oblivion tomorrow too!").
There are a number of ways that you can solve this problem. Once you find
the first correct occurrance of the word you can use '*' to find the next
occurrance of it as a whole word. (* will search forwards, # will search
backwards.)
What if you are nowhere near the first occurance of the whole word?
To solve this you have to wrap the text you are looking for with angle brackets
- which you have to 'escape' with '\'.
For example, if you want VI to search for the word 'tux' and don't want the
word 'tuxedos' to be found, this is what you'd type:
/\<tux\> followed by the return key.
This solution is the better one, mostly because you can use it to search for a
phrase or a certain combination of words like "if you".
You can search for regular expressions too, just like with sed so if you need
to find any number you can do /[0-9] and so on. Regular expressions are much
too complex for me to write about in this tutorial, entire books have been
written about them. Though of course this mightn't stop me from writing a
tutorial on them later on. Don't hold your breath though!
Search and Replace.
Lets say that you need to replace a word with a different one. How would you
do it?
Here's how (this also works on portions of words).
Type :s/word/replacement/ (though the last / is really needed).
That works just fine for replacing that word just once, if you need to do it a
number of times you need to use the g modifier:
:s/word/replacement/g
Which is all well and good if the word you want to replace only ever occurs on
the same line as the other occurrances. Fat chance of that in the real world.
So how do you do that then?
What you can do is this, type :.,.+ and then a number followed by s/word/replace/g
The number is taken to be the number of lines that you want the substitute
command to process less one. So if I have a paragraph consisting of five lines and I
want to swap 'Fred' with 'Barney' I'd use:
:.,.+4s/Fred/Barney/g
instead of moving to each line and typing :& to repeat the last substitution.
To do this to every line in the file you can either use the hard way or the
easy way.
I'm going to describe the hard way first - just for the sake of completeness
than for any other reason.
What you need to do is this:
Go to the first line in the file (with 1G), press <ctrl-G> to get vi tell you
how many lines are in the file (lets say it's 105) and then use:
:.,.+104s/Fred/Barney/g
But this is way too long-winded and is something that you'd rather not do.
The simplest way is to use:
:%s/Fred/Barney/g
You should be aware though that this moves the insertion point to where the
last replacement occurred, so use := to find out which line you have the
insertion point on before you do anything so you can use nG (where n is
the line number) to get back to that line straight away, with out any
faffing around.
That's great, but what if you want to confirm which occurances of the word are
supposed to be replaced with the other word. How would you do that?
Setting this up is really quite simple, you need to use the confirm modifier
in conjunction with the global one (which is already there). So you'd use
:.,.+Ns/word/replacement/cg where N is again the number of lines that you want
affected (less/minus 1).
One particular thing that I was asked about is the annoying fact that if you
edit a text file which was edited under DOS or Windows in your linux vi
session there are a lot of weird ^M characters displayed. If you are using vi
to edit perl scripts or HTML pages with JavaScript in them these ^M characters
will cause problems. These ^M characters are called Carriage Returns.
You can use the substitute command to get rid of these.
Initially you might try to do this with
:%s/^M//g (where N is again the number of lines)
This simply won't work because the command is looking for two seperate
characters, '^' and 'M'. What you need to do is this:
:%s/<ctrl-v><return>//g
What <ctrl-v> does here is tell the substitute command that the following
keystroke is a part of the text to be replaced. So if you wanted remove all
tab characters from the document you could use:
:%/<ctrl-v><tab>//g
You insensitive...
Bill Meyer asked me about case insensitive searches.
It's very simple to do a case insensitive search & replace. All that it means
is using the 'i' modifier. So to change all occurrances of both 'betty' and
'Betty' to 'Wilma' you'd use this:
:%s/betty/Wilma/gi
If though you want to change all occurrances of 'ken' and 'Ken' to Kenneth,
you have to be more careful or you could have the word broken changed to
broKenneth. All you have to do is wrap the word being replaced with those
escaped angle brackets.
:%s/\<ken\>/Kenneth/gi
You might be tempted to try :/foo/i to find all occurrances of foo and Foo
or some such variation. But you'd be wrong.
To do this use
:set ic
and then perform your search (ic being an abbreviation for 'ignore case').
If you then want to do a case sensitive search you will need to use the
following:
:set noic
Abbreviations & Autocorrect
The support for abbreviations in vi is really quite handy, both for taking
shortcuts (for example typing 'sw' as a word and having it replaced with the
word 'software') and for correcting common spelling mistakes (replacing 'Adn'
with 'And').
This is a very simple thing to do, for example
:ab sw software
tells vi that everytime I type sw as a whole word it will replace it with the
word software.
Similarly I have a different abbreviation set up to replace ailug with the
words "Irish Linux Users' Group":
:ab ailug Irish Linux Users' Group
You can see from this that you do not have to escape the words that the
abbreviation represents.
There's just one slight problem that you might encounter - if you try to
redefine an abbreviation, you'll find that the moment you get as far as
specifying what the abbreviation represents, that the abbreviation itself will
get expanded to the older meaning/representation.
You must unabbreviate an abbreviation before you can redefine it. To do this
type :una followed by the name of the abbreviation and then redefine it.
You can see a list of all abbreviations that you have defined by using
:ab on
it's own.
Naturally you wouldn't want to type in a hoard of ab commands
each time that you open a file. It makes much more sense to set up these
abbreviations in a common file that vi can reference when you start it, the
.exrc file (or .vimrc if you're using vim).
This is a text file which can contain (amongst other things) abbreviation
commands and set commands (without the colon at the start of the line).
Filters.
One nice thing about vi is that you can filter your document through an
external program to replace it's text with the output of the filter.
Let me explain.
Suppose you are compiling a list of the reference books that you own (for
whatever reason). For example:
Perl Power!
CGI Programming in C & Perl
Information architecture for the World Wide Web
Perl 5 Desktop Reference
Webmaster in a nutshell
Linux in a nutshell
Perl Cookbook
HTML 3.2 plus How-To
The new hacker's dictionary (third edition)
Wouldn't it read better if it were in alphabetical order? And even better
if you did not have to order the titles of these books 'by hand'?
To do it you should use the following, :x,y!sort, where x is the line number
where the list starts and y is the line number where it ends. This would
result with:
CGI Programming in C & Perl
HTML 3.2 plus How-To
Information architecture for the World Wide Web
Linux in a nutshell
Perl 5 Desktop Reference
Perl Cookbook
Perl Power!
The new hacker's dictionary (third edition)
Webmaster in a nutshell
If you know the number of entries in the list and couldn't be bothered to
specify the line numbers you can type n!!sort (note that the colon is
missing and you should replace 'n' with the number of entries that you want
affected).
Word Count
A better use of filters comes to mind, and that's to get a word count of the
document (1752 words and counting!). To do this type:
:%!wc
This will display a group of three numbers like, "206 1765 9995" (and pretty
much nothing else). These numbers indicate the number of lines, words and
characters. To get the document text back press 'u'.
Finishing Off
Well that's pretty much it for now, between this tutorial and the last one you
should have an idea of how to edit files in vi, how to find text, replace it
and also how to use filters to sort text alphabetically and get a word
count.
These are the 'essentials' that I think should be know by anybody who wants to
use vi effeciently, though of course vi gurus are probably shaking their heads
in disbelief saying 'he didn't cover...'.
As always, please feel free to email me with corrections and anything else that
you think I ought to cover at a later stage [whether I will or not is another
matter - but there's always a chance].
The Declan clause.
This tutorial was written by Ken Guest, http://technobrat.net.
Copyright © Ken Guest 1999.
Publication of this work in any printed or electronic form in part or in whole for non private use without (a) the inclusion of the above copyright notice (b) written permission of the author is an infringement of copyright and thus prohibited by law and international convention.
Credits
Thanks to:
Bill Meyer,
John Allen,
Rob Hill and
Tethys
for corrections and guidance!
Also by Ken Guest
- Samba Tutorial; using Samba for filesharing and sending messages between Linux and Windows.
- vi Tutorial #1, an introduction to vi and ViM.
Please tell us what you thought of this tutorial:
|