Fluent vi
A few useful commands to help you become fluent in the Unix text editor vi.
Tom Reid
3/8/20235 min read
When I first started out in my programming career, the first PC I used that ran a UNIX-like operating system was called a microVAX II built by the now-defunct Digital Equipment Corporation (DEC for short). Its operating system was called Ultrix which of course was a Unix derivative. And, like all Unix derivative systems, it came with a full-screen editor called vi. So I had to get to know vi — and pretty quickly. Boy, I wish I had the handy list of commands that I’ll show in this article back then.
There seems to be a lot of talk nowadays about the vim editor, which I guess is a derivative of vi and is supposed to be better in some ways. My understanding is that most if not all of the vi commands I show can work on vim as well. Note this assumes you know the basics of vi already. Unless otherwise stated most of the vi commands highlighted in this article should be typed in whilst you are in command mode of vi NOT in insert mode. If you don’t know what that last sentence means, you don’t know the basics yet — get learning those first!!
Useful vi commands
Crucial to the goal of becoming fluent in vi is the concept of marks. Marks are simply a way of marking different sections or records of your buffer in vi so that you can refer to them in subsequent commands. Usually, these commands will involve cutting and/or pasting. To mark a line of text use the m command followed by a letter in the range a to z, for example, ma will mark the current line with the letter a. Note that you won’t see the characters ‘ma’ onscreen when you type this command (if you do it means you are in INSERT mode!), it’s just an internal label maintained by vi. In the following examples, expressions in brackets may be typed instead of the corresponding expression before the brackets. For example d(y)’a stands for deleting or yanking lines and means you can type d’a or y’a. The difference between deleting and yanking lines is that deleted lines are removed from the buffer whereas yanked lines are left in place.
Cut and Paste between a marked line and the current line.
Goto the line you want to start cutting from. Type ma then move the cursor to the line you want the cut to end at. Then for example you can …
‘a — goto the start of the line marked with a
`a — goto the cursor position marked with a
d(y)’a — delete(yank) all lines between mark a and the current line
P(p) — put back deleted or yanked lines before(after) the current line
“xd(y)’a — delete(yank) lines into a buffer named x, buffer x is overwritten.
Use capital X to append lines to buffer x keeping what’s already in buffer x. This variant is useful when you want to cut and paste between two or more opened files.
Cut and Paste between two marked lines.
Go to the start line to be marked. Type ma. Go to the end line to be marked. Type mb. Then for example:-
:’a,’b d(y) — deletes(yanks) lines between the two lines marked with a and b
:’a,’b mo(co) 5 — moves(copies) lines between marks to after line 5
:’a,’b mo(co) 0($) — moves(copies) lines between marks to top(bottom) of the file
:’a,’b mo(co) . — moves(copies) lines between marks to after the current line
Of course, you can do all of the above commands on numbered lines also, for example
:13,20d — deletes lines 13 through 20 inclusive
:3,5 mo(co) 7 — move(copy) lines 3 to 5 after line 7
:.,+Nd — delete current plus next N lines
Finding/substituting text
:s/abc/xzy/ — substitute the first occurrence of abc with xyz on the current line only
:s/abc/xzy/g — substitute all occurrences of abc with xyz on the current line only
:100,150s/abc/xyz/g — substitute all abc’s with xyz’s between lines 100 and 150 only
:’a,’bs/abc/xyz/g — substitute all abc’s with xyz’s between lines demarcated with the marks a and b
:s/abc/U&/g — capitalise all abc’s on the current line
:5,/ABC/s/XYZ/TOM — substitute the string XYZ with TOM between line 5 and the next line that contains the text ABC
:%s/^…X/…Y/g — substitute all X’s in 4th character position on all lines with a ‘Z’
g/abc/s/123/456/g — on all lines containing abc substitute 123 with 456
/(?)abc — find next(previous) occurrence of abc starting from current cursor position
n(N) — find next(previous) occurrence of a search string
:%s/abc/xyz/g — substitute all abc’s with xyz’s in the whole file
The remembered text in substitutions
The remembered text in substitution patterns is defined by the & character or n where n is a number between 1 and 9. The & represents the last regular expression found and the n variant is defined by any regular expression contained within escaped brackets reading from left to right. For example in the search expression /^X(.T)xyz(xxx) where we are trying to find a line beginning with X followed by any single character followed by a T followed by xyz followed by 3 x’s, the 1 corresponds to .T and 2 corresponds to xxx.
Some examples should clarify.
:s/X/&123/ — change X to X123 in current line
:s/.$/X&/ — put an X before last character in current line
:s/(.*) HARRY (.*)/2 1 HARRY/ — change a line containing DICK HARRY TOM to TOM DICK HARRY
Miscellaneous Commands
:# — display the current line number
:map s 3dw — map pressing s in command mode to be equivalent to deleting 3 words
:map! s 3dw — map pressing s in insert mode to be equivalent to deleting 3 words
^v — allows entering of control characters such as escape
NJ — join N lines after the current line to the end of the current line
!! O/S command — put the result of the operating system command into the current buffer at the current cursor position
N| — goto character N of the current line
@x — runs the editor commands contained in the named buffer x
“dp — undo the dth last delete (up to a max of nine) of 1 or more lines
:set ic — ignore case when searching text
:set nows — don’t wrap around file when conducting searches
:set number — display line numbers
:set — display all options set
:set all — display all settable options
cw — change word
c3l — change the next 3 characters only
:map #ndd — map function key n to delete the current line
% — find the matching bracket
i — start input mode at the current cursor position
O — open a new line above the current one and start input mode
Ndd — delete N lines starting at the current line
Ndw — delete the next N words
Moving about in the file (in command mode)
Nj(k) — move cursor down(up) N lines
Nh(l) — move cursor left(right) N characters
:G — goto end of file
:1 — goto start of the file
$ — goto end of the current line
0 — goto start of the current line
:130 — goto line 130
W — move to the start of the next word
^F(^B) — scroll forward(back) one screen
^D(^U) — scroll forward(back) a half screen
The numbered buffers
vi automatically saves deleted (whole lines of) text into nine numbered buffers (1–9) which can be used to retrieve accidentally deleted text. The most recent delete is in buffer number 1. To retrieve this line use the command “1p(P) to put back the line after(before) the current line. The dot command cycles through each of the buffers in turn therefore a quick way to see all the contents of all nine buffers is to use “1p……..
Initialisation commands
We can put vi initialisation commands in a file called .exrc in our home directory. When vi is invoked it reads this file and the commands contained in it are executed and are in force for the whole of the edit. A typical .exrc file might contain commands such as
:set ic — ignore case
:set nows — no wrapscan
:map rm 5dd — map rm to delete 5 lines
:set nomagic — characters such as *,? and . lose their special meaning
:set number — turn line numbering on
tel: +44 (0)780 392 2285 email: info@cirrusdata.uk
©2023 by Cirrus Data Limited