Editing Text Files with vi in a Pure CLI Environment

5 min

vi is an extremely lightweight text editor with many basic features, usually pre-installed on most Unix systems. Both Ubuntu and macOS come with the vi editor built-in. To flexibly modify text files on systems with only a CLI interface, learning to use the vi editor is essential.

Getting Started

To use the vi editor, you need to enter the following command in the terminal:

vi [options] [file(s)]

This will open the vi editor, allowing you to edit files through the process described below. Now let’s see what we can actually do after entering the vi editor.

flowchart TD
    Start([Start vi]) --> Command[Command Mode]
    
    Command -->|"/ ?"| Other[Other Commands]
    Other -->|Enter| Command
    
    Command -->|":"| Last[Last Line Mode]
    Last -->|"wq"| End([End vi])
    Last -->|"q!"| End
    Last -->|"q"| End
    
    Command -->|"i,a,o,r,c"| Insert[Insert Mode]
    Insert -->|Esc| Command
    Command -->|"ZZ"| End

Command Mode

As shown in the flowchart above, after entering the vi editor, you will directly enter Command Mode. In this mode, you can use various commands to move the cursor, edit text, copy and paste, enter Insert Mode, enter Last Line Mode and more.

These commands follow the syntax below:

[number of times to execute operation] operation [number of targets to act on] target

Moving the Cursor

You can use Ctrl + G to check the current cursor position. Here are some commonly used cursor movement commands:

CommandAction
1G, ggMove to the first character of the first line
GMove to the first character of the last line
LMove to the first character of the last line on the screen
^Move to the first non-whitespace character of the current line
0Move to the first character of the current line
$Move to the last character of the current line
wMove to the first character of the next word
bMove to the first character of the previous word
}Move to the next paragraph

Editing Text

CommandMeaningAction
dddeleteDelete the current line
7dddeleteDelete the current line and 6 lines below (7 lines total)
d$, DdeleteDelete all characters from the cursor position to the end of the line
5dwdeleteDelete 5 words
xdeleteDelete the character under the cursor
XdeleteDelete the character before the cursor
uundoUndo the last action

Copy and Paste

CommandAction
y2WCopy two words to the right from the current cursor position
4ybCopy four words to the left from the current cursor position
yy or YCopy the current line
pPaste the copied text after the current cursor position
PPaste the copied text before the current cursor position
5pPaste the copied text from the buffer after the current cursor position five times
YCopy the current line
yyCopy the current line
" x yyCopy the current line to register x
yeCopy to the end of the word
ywSimilar to ye, but includes the whitespace after the word
y$Copy the rest of the line
" x ddDelete the current line and store it in register x
" x dDelete and store in register x
" x pPaste the contents of register x
y]]Copy to the next section heading
JJoin the current line with the next line
gJSimilar to J, but without inserting a space (vim and gvim)
:jSimilar to J
:j!Similar to gJ

Entering Insert Mode

CommandMeaningAction
aappendAdd text after the cursor
AappendAdd text after the last character of the current line
cwchangeEnter replace mode until the end of the current word
ccchangeDelete the entire current line and enter insert mode
c$, CchangeEnter replace mode until the last character of the current line
iinsertAdd text before the cursor
IinsertAdd text before the first character of the current line
oopenOpen a new blank line below the current line and place the cursor there
OopenOpen a new blank line above the current line and place the cursor there
RreplaceEnter replace mode, where typed characters overwrite characters under the cursor
ssubstituteReplace one character and enter insert mode
SsubstituteDelete the entire line content and enter insert mode

Entering Last Line Mode

Simply type : to enter Last Line Mode.

Insert Mode

As the name suggests, this is the mode for entering text. In this mode, you can type text just like in a regular text editor. When you want to return to Command Mode, simply press the Esc key.

Last Line Mode

File Operations

CommandAction
: n, m w fileWrite lines n through m to a new file
: n, m w >> fileAppend lines n through m to an existing file
:r filenameRead and insert the contents of filename at the current cursor position
:wqSave the buffer and exit
:wSave the current buffer and remain in the editor
:w filenameSave the current buffer to filename
:w! filenameOverwrite filename with the current content
:w!Force write the file (override protection)
:w! fileOverwrite file with the current content
:w %.newWrite the current buffer to a file named file.new
:qQuit vi (fails if there are unsaved changes)
:q!Quit vi without saving the buffer
:QQuit vi and start ex
:viReturn to vi after the Q command
ZZExit vi, saving the file only if changes were made since the last save
%Represents the current filename in edit commands
#Represents the alternate filename in edit commands

Search and Replace

CommandAction
:s/john/jane/Replace john with jane on the current line, once only
:s/john/jane/gReplace every occurrence of john with jane on the current line
:1,10s/big/small/gReplace every big with small on lines 1 through 10
:1,$s/men/women/gReplace every men with women throughout the entire file
:'<,'>s/this/that/gFirst press <Ctrl+V> in Command mode and use arrow keys to select a range, then type : to replace this with that (vim, gvim only)
:s/ \<tim\>/tom/Replace only the complete word tim with tom, not partial matches of tim within strings
:%s/terrible/wonderful/gcUse the c option for interactive replacement of terrible with wonderful (vim, gvim only)
:%s/^/ \=line(".") . ". "/gPermanently add line numbers to the beginning of all lines in the buffer (vim, gvim only)

Environment Settings

Setting Abbreviations

CommandAction
:ab in outDefine in as an abbreviation for out in Insert mode
:unab inRemove the abbreviation for in
:abList all abbreviations

Setting Mappings

CommandAction
:map string sequenceMap a character string to a sequence of commands. Use #1, #2, etc. to represent function keys
:unmap stringRemove the mapping for the character string
:mapList mapped character strings
:map! string sequenceMap a character string to a command sequence for input mode
:unmap! stringRemove the input mode mapping (may need <Ctrl+V> to quote characters)
:map!List mapped character strings in input mode
qxRecord typed characters into the register of the specified letter x (vim and gvim)
qStop recording (vim and gvim)
@xExecute the register of the specified letter x. Use @@ to repeat the last @ command

Setting Options

CommandAction
:set xEnable boolean option x, display values of other options
:set noxDisable option x
:set x=valueSet the value of option x
:setDisplay changed options
:set allDisplay all options
:set x?Display the value of option x
TIP

If you want to permanently save these environment settings, you can write the desired commands into .exrc.