vi and vim cheat-sheet

You can either hate vi editor or love it. It’s usually hated by the people who don’t understand how to switch between the normal, insert an command modes and how to exit vi/vim. vim is just short from “vi IMproved” and can show you nice syntax highlighting and bunch of more features compared to vi. While many of the instructions below should work on both vi and vim, some advanced ones are definitely vim-only. So, if it does not work in vi, consider using vim.

Always make sure that caps lock is OFF and you know your keyboard layout.

Opening files with vi in command-line

To open a file in specific line number with vi use +line number and to open file on first occurrence of a search string use +/string , to open files in tabs with vi, use -p option:

# open known_hosts file on a line 378 where you might have a conflicting key
$ vi +378 .ssh/known_hosts
# open .bash_history on a line with first occurrence of a string password
$ vi +/password .bash_history
# open 3 files
$ vi file1 file2 file3
# open 3 files in tabs
$ vi -p file1 file2 file3
# open all files with yaml extension from current directory
$ vi *.yaml
# open all files listed by previous command as tabs. NB! there is a default tab number limit. Something like 10.
# open all files containing thereisnofish as tabs
vi -p `grep -iRl thereisnofish ./*`
# just open vi without any file
$ vi

Vi modes

Once you can understand the modes you can explore some of the features, why vi/vim are the best ever command-line text editors, like repeating actions, recording and playing back macros, editing multiple files.

  • NORMAL (default) mode. This is the mode where you are when vi starts. In this mode you can move cursor around, you can search strings, delete things and you can go from normal mode into insert mode and command mode.
  • INSERT mode. This is the mode you can manually add new stuff to the file. You can go back to normal mode by pressing escape. Easiest example is that press “i” to go to insert mode, type in something and press escape to go back.
  • COMMAND mode. In this mode you can save, exit, search&replace etc. You can go to command mode by pressing colon “:” while you are in normal mode. You can go back to normal mode by pressing escape. Easiest example is that press “:” to go to command mode, type in “q!” (q=quit and !=force) and press enter to exit vi without saving any changes. Typing “:qw” and enter would mean “quit and save”.

If you read and understand these few lines above about modes you should be able to open files with vi, change file and exit. Basic stuff but important to understand before going any further.

Few important notes

IMHO most important button of the vi is . (dot). It repeats last thing you did. If your last action was deleting a line, pressing . will delete another line.

You can use numbers to do something multiple times by prefixing a command with numbers. Example if your last action was deleting a line, pressing 5. (5 followed by .) will delete 5 more lines.

Commands are case-sensitive! Remember caps lock? If vi acting weird and does not do what you want, you have your caps lock on.

Word is a string from cursor up to the next space or punctuation. As an example, IP address consists of 7 words. Always.

NORMAL MODE

Moving around in vi in the normal mode

Moving around in file opened in vi takes some practice. Cursor keys are not the only ones and are really slow. Fastest way to move in any direction would be to search the string and your cursor will be dropped almost instantly to the right place, at least if to compare with scrolling. Next fastest way for vertical scrolling would be CTRL-f and CTRL+b while horizontally jumping by word with w/b/W/B will be definitely faster than just scrolling manually 1 character/position at the time.

Command Description
up-arrow or kgo to the previous line, up
down-arrow or jgo to the next line, down
left-arrow or hgo one character left
right-arrow or l (lowercase L)go one character right
1Ggo to the FIRST line of the file
50Ggo to the line 50
Ggo to the LAST line of the file
$go to the end of line
0 (zero) or ^go to the beginning of line
w,Wgo to the beginning of next word, to the right. W skips one punctuation or space.
b,Bgo to the beginning of previous word, to the left. B skips one punctuation or space.
ego to the end of the word
CTRL+fgo to one screen/page forward or scroll down.
CTRL+bgo to one screen/page backwards or scroll up.
CTRL+dgo to half the screen/page forward or scroll down.
CTRL+ugo to half the screen/page backwards or scroll up.
Hgo to the upper left corner of the screen
Mgo to the beginning of the line in the middle of the screen
Lgo to the lower left corner of the screen
z+ENTERreposition window so that cursor is in the top
z-reposition window so that cursor is in the bottom
z.reposition window so that cursor is in the middle
gt, gTSwitch to next tab, switch to previous tab
CTRL+w followed by kSwitch to upper window when screen has been split
CTRL+w followed by jSwitch to lower window when screen has been split
CTRL+w followed by hSwitch to window in the left when screen has been split
CTRL+w followed by lSwitch to window in the right when screen has been split

Undo and redo in vi in normal mode

If you are used to fire CTRL+z to undo changes, then its useful to know that it will not work in vi. Instead it stops vi process and backgrounds it. You can get it back by running command fg in your shell.

CommandDescription
uundo
CTRL+rredo – undo last thing you undid with pressing u. Re-doing just the last thing you undid can be done also with . (dot).
Uroll back all changes you did on the last edited LINE

Entering insert mode for inserting, replacing & changing text

All the commands below should be fired in NORMAL mode and they take you to INSERT mode, press escape to finish and go back to normal mode.

Command Description
iinsert text to the left of cursor.
I (capital i )Insert text to the beginning of line.
aAppend text to the right of cursor.
AAppend text to the end of line
rOverwrite single character under the cursor. Goes back to normal mode after you input single character.
ROverwrite text from cursor to the right
C, c$Replace text from cursor to the end of line
3CReplace text from cursor to the end third newline. Current line and 2 lines below.
cwChange Word – replaces word
7cwChange 7 Words – replace 7 words like IP address
oAdd new line after current line
OAdd new line before current line
ssubstitute character under cursor with one or more characters. Like r and i mixed.
S, ccsubstitute entire line. Clears the line, otherwise same as pressing C in the beginning of the line.

Deleting / truncating / changing / joining in normal mode

You don’t need to go to the insert mode and start deleting text with backspace or delete. There are faster ways described in table below. You run those commands in normal mode and you remain in normal mode (no need for pressing escape).

CommandDescription
xDelete character under cursor
XDelete character after the cursor
5xDelete 5 characters – the one under cursor and 4 which follow.
ddDelete line under cursor
100ddDelete 100 lines – line under cursor and 99 lines below. Also useful for truncating short files, might be easier to remember than other ways.
dwDelete word -delete from under the cursor to the end of the word
7dwDelete 7 words like IP address
dbDelete word before the cursor
DDelete from cursor to the end of line
3DDelete from cursor to the end of third newline. Current line and two lines below.
dGDelete from current line to the end of file. It is easiest way for truncating entire file if you happen to be on the first line with your cursor. if not, then press 1G to go there.
CTRL+aincrease number under cursor by one. if cursor is not on a number, then increases first number after cursor by one
CTRL+xdecrease number under cursor by one. if cursor is not on a number, then decreases first number after cursor by one
JMoves cursor to the end of line and joins next line with current one. Extremely handy to replace newlines with space.

Copy & paste in vi 1/3 – general stuff

If you have copied something from some other application or from vi screen to clipboard, then you need to go to insert mode before pasting the clipboard. Otherwise your pasted string is interpreted as line of commands right up to first command which takes you into insert mode. Keys to copy to and from clipboard depend on your application/terminal config. Linux default combinations are CTRL+insert for copy and SHIFT+insert for paste.

Copy inside vim is YANK – this has nothing to do with clipboard. Yanked contents will be stored by default in vi general buffer.

CommandDescription
yy or Y yank line
20yy or 20Yyank 20 lines – current line and 19 below
ywyank word
7ywyank 7 words like ip address
pput/paste yanked contents after cursor. If you yanked words, they will be pasted after cursor. if you yanked a line, it will be pasted after current line.
Pput/paste yanked contents before cursor. If you yanked words, they will be pasted before cursor. if you yanked a line, it will be pasted before current line.
100pput/paste yanked content 100 times. If you yanked a line, it will make 100 copies of it.

Copy & paste in vi 2/3 – moving lines and words with delete?!!

Everything you delete are yanked – deleting something with d/D/x/X commands will put deleted contents into general yank buffer so you can just use p to undo/restore. That allows you to move words or lines like so:

To move 3 lines press 3dd which deletes 3 lines (and yanks them). Move to the new location where you want these 3 lines and press p to put them after current line or P to put them before current line. That’s it! No need to yank something paste them to new location and then going back to original location to delete them.

Copy & paste in vi 3/3 – The Buffers

Vi has ability to store yanked text to internal buffer named a to z. These buffers could be compared with multiple items in the clipboard but there is also option to append something to already existing buffer – you can put things together in one or more buffers and then just go and put/paste somewhere, like new file. You don’t get any visual feedback, so vi buffers are like D&D in your head – to slay a dragon, one must start with (double quotes). Using uppercase letters as buffer names will append to the buffer.

CommandDescription
“a10dddelete 10 lines and add them to buffer a
“appaste buffer a contents below current line
“b5yyyank 5 lines to buffer b
“Byyyank line and append it to buffer b
“bPput/paste buffer b contents above current line
“c4ywyank 4 words to buffer c
“C3ywyank 3 words and append to buffer c (appending adds newline)

Buffers remain in memory until you close the vi. Its useful to copy paste data from one file to another using buffers. Open one or more files, copy parts of it to buffers, open or just switch to next file and paste the buffers.

Searching in vi

Use / or ? to search strings. Press enter to begin searching.

Command Description
/searchstringforward search
?searchstringbackward search
nforward search, FIND NEXT
Nbackward search, FIND PREVIOUS
fx & ;find/jump to first occurrence of character x in current line. press ; semicolon to find next x. Search scope is very limited, only line where your cursor is and after, right side of the cursor.

You can do semi-automated search & replace if you search something, then replace it and after that just press n and . Extremely handy to replace similar parameters like IP addresses or host names in one or more files without using search&replace command in command mode which does not let you preview the results. Note that if you are modifying more than one file at the time, you can jump to next file and just press n to search last thing.

COMMAND MODE

You can go to command mode from normal mode by pressing : (colon). After that enter your command and press enter.

Command mode 1/3 – general stuff

CommandDescription
:wwrite, save file
:w!force write file – usually needed when you want to update read-only files
:w newfilewrite a copy of open file to “newfile”. open file remains open in vi, it does not switch to newfile.
:qquit
:q!quit and ignore changes
:wqsave and quit (same as command ZZ in normal mode)
:wq!force save and quit (read above)
:r filenameread contents from file and place them after the line with cursor
:e filename
😮 filename
:open filename
close current file and open file for editing. if you opened multiple files, it closes only currently open file and leaves the rest.
:10 r filenameread contents from file and place them in currently open file after 10th line
:1,16w new.shwrite lines 1 to 16 into file new.sh. If file exist and you want to truncate its previous contents use ! like :1,16w! new.sh
:1,16w>> new.shappend lines 1 to 16 into file new.sh.
:nopen next file, useful if you opened multiple files with vi. use :n! to open next file without saving changes in current one.
:N or :prevopen previous file. useful if you opened multiple files with vi
:rewrewind – go back to first opened file. useful if you opened multiple files with vi
:10go to line 10
:!/bin/bashrun shell command /bin/bash . One reason why you should never grant sudo privileges to run vi or edit some file as root.
:tabcloseclose current tab
:tabonlyclose all other tabs except current one
:qa!close all tabs and exit without saving changes
:wqaclose all tabs and exit with saving changes
:tabedit filenameopen file in new tab and switch to that tab
:tabsshow list of tabs and open file names with paths
:tabedit filename |tabedit filename2 open multiple files into tabs from command mode
:vs or :vsplitsplit screen vertically
:sp or :splitsplit screen horizontally

Command mode 2/3 – search & replace and regular expressions

Search and replace in vi is substitute. When running substitute in command mode, you can define a scope or range where to perform it, search and replace strings and flags.

General substitute command syntax is like this

:[scope]s/searchstring/replacestring/flag

Search scopesDescription
%entire file
16line 16 only
1,16range: lines 1 to 16
.current line
.+77th line under current line
.,.+7range: 8 lines from current line (.) to the 7th line after current (.+7)
$last line
g/somestring/only line(s) containing somestring

It is possible to use regular expressions in search strings

Regular expressionMatches
.Any single character
*Any previous character
.*Any character
^Beginning of the line
$End of the line

Substitute flags

Flags in the end of substitute command can be combined, you can use more than one.

FlagDescription
gglobal – perform substitution on entire file which is currently being edited.
cask confirmation for each replace
I (capital i )case sensitive search

Example searches are below, feel free to combine any other substitutions from the scopes, regexes and flags above.

CommandDescription
:%s/foo/barshould replace first occurrence of word foo with bar in currently opened file. testing showed various results like replacing several but not all foo-s. Better use the next example.
:%s/foo/bar/greplace all occurrences of string foo with string bar in entire file.
:%s/^#//gcomment in / remove hash from beginning of all lines in open file. does not work if # has indentation in the front.
:%s/^ *//gremove all spaces from the beginning of the line. will not remove tabs.
:%s/^\s*//gremove all white-space from the beginning of the line. \s indicates white-space which matches both space and tab. To search tabs only use \t.
:%s/ *$//gremove all spaces from the end of the line. will not remove tabs.
:%s/E/x/gIreplace all uppercase E characters with lowercase x characters
:g/foobar/foo/bar/greplace all foo-s with bar on lines containing foobar

Command mode 3/3 – Parameters

Its possible to set various parameters in vi/vim with set command in command mode. Most common of them is probably showing/hiding line numbers.

CommandDescription
:set allDisplay all supported parameters and their current values if any.
:set number
or short
:set nu
Display/show line numbers in vi. if you want to copy it afterwards from screen to clipboard, you might get the line numbers copied too.
:set nonumber
or short
:set nonu
Hide linenumbers
:set listDisplay non-printable characters. Extremely handy to show newlines and identify whitespace in the end of line.
:set nolistHide non-printable characters
:set autoindentmake vi to follow indentation of a previous line when you add newline. generally pads line beginning with spaces to the lenght of what previous line had.
:set noautoindentturns off indentation/padding.
:set showmatchshows matching parenthesis when you type the closing parenthesis. Its not exactly a highlighting, cursor just jumps to opening bracket and back.
:set noshowmatchturns off the matching bracket showing.
:set showmodeshows you mode in the last line of the screen when you are in insert and/or macro recording mode
:set noshowmodeturns off mode showing

VI MACROS

When . (dot) allowed you to repeat LAST action, then macros allow you to repeat many of them – a sequence of these actions what you previously recorded, any number of times. Macro recording and playback is done in normal mode. To start recording, press q in normal mode followed by one lowercase letter which is assigned to macro name for example qa. While you record you can use all the vi features&commands to do whatever you want (to repeat). Press q again to stop recording. If you want to playback the macro then press @ followed by macro name, for example @a. If you want to playback macro named a 10 times press 10@a . This very much resembles scientific calculator programming (Citizen, Электро́ника МК-61, MK-52 etc.) – you have to think in steps.

Sample macros

Numbered list

Assuming, you have a file with 100+ lines of text and you want to add increasing number to the front of each line starting from 1 up to 100 and a space between number and text. Open file and follow steps in first column.

CommandsDescription
1 Ggo to line 1 – optional, you are probably in the first line already
I (capital i)Insert into the beginning of line
1 followed by space and escadd “1 ” to the beginning of first line, go back to normal mode
now you should have first line with prefix 1 done. make sure you are in first line before starting macro recording
q arecord macro with name a
0 y wgo to beginning of line, yank word (line number)
j 0 Pgo down one line, go to beginning of the line and paste word in the front of the cursor (line number on previous line)
0 CTRL+ago to beginning of the line and increase number under the cursor by 1
q stop recording
by now you should have two numbered lines. make sure you are on second line before running a macro… or you might just get list to 99
99@arun macro a 99 times

CSV file into SQL with vi

Assuming that you have csv file with 4 fields like this:

“abc”,”abc”,”abc”,”abc”
“abc”,”abc”,”abc”,”abc”
“abc”,”abc”,”abc”,”abc”

And you want to convert it to SQL insert statements with incrementing primary key like this:

insert into table1 values (1, “abc”,”abc”,”abc”,”abc”);
insert into table1 values (2,”abc”,”abc”,”abc”,”abc”);
insert into table1 values (3,”abc”,”abc”,”abc”,”abc”);

Open file and follow steps in first column.

CommandsDescription
1 Ggo to line 1 – optional, you are probably in the first line already
I (capital i)Insert into the beginning of line
insert into table1 values (1, ESCtype in the first part and go back to normal mode with escape
A ) ; ESCappend ); to the end of line and go back to normal mode with escape
you should have now converted your first line to SQL. make sure you are on first line before starting to record
q arecord macro with name a
0 7 y wgo to beginning of the line and yank 7 words
j 0 Pgo down one line, go to beginning of the line and paste word in the front of the cursor
A ) ; ESCgo to the end of line and add );
0 5 w CTRL+ago to the beginning of the line, jump to the 5th word and increase it by one
qstop recording
by now you should have two lines with sql syntax. make sure you are on second line before running a macro
N@arun macro “a” N times. replace N with the number of lines you want to convert.

Various other commands

Old Estonian proverb: “There are 3 things which are certain in life: death, taxes and there are always more vi commands than you know.”

Command Description
CTRL+gdisplay file name, number of lines, current line and column number where the cursor is
CTRL+l (lowercase L)refresh the screen, might be handy if there are some glitches
CTRL+hmove backwards 1 character in INSERT MODE
CTRL+wmove backwards 1 word in INSERT MODE
CTRL+umove to the beginning of insert in INSERT MODE

Indentation in vim

I personally like indentation with spaces instead of tabs and indentation width 2 spaces so there is an example configuration below how to do that. To make it easier, I add those commands into /etc/vimrc to make it global or into ~/.vimrc to apply it only to my user, that saves me from typing those commands in all the time. Also it seems that automatic indentation is pretty useless if you have multiple commands on the same line.

set expandtab
set shiftwidth=2
set softtabstop=2
filetype plugin indent on

where:

  • expandtab – uses spaces instead of tabs.
  • shiftwidth=2 – sets indentation to 2 spaces
  • softtabstop=2 – sets how many spaces you get when you press tab
  • filetype plugin indent on – enables automatic indentation

After you

CommandDescription
== automatically indent current line
gg=GGo to first line, and auto-indent file until the end of file. of course you can omit the gg and indent from any line where your cursor is, until to the end of file
5==indent 5 lines automatically
>>indent current line by one indent
<<remove one indent from current line
5>>indent 5 lines by one indent
5<<remove one indent from 5 lines

If you found this useful, say thanks, click on some banners or donate, I can always use some beer money.