The Ultimate Guide to Advanced VI Editing Commands

If you work with Linux servers, you probably know the basic Vi commands:

i       insert text
Esc     leave insert mode
:w      save
:q      quit
:wq     save and quit

That’s enough to edit a configuration file.

But it’s not enough to edit files quickly.

The real power of Vi starts when you stop thinking of it as a text editor and start thinking in terms of motions, operators, objects, and commands.

Instead of moving the cursor one character at a time, you can tell Vi exactly what you want:

delete this word
change everything inside these quotes
jump to the next occurrence
replace this value
move this line
repeat that change

For example, instead of doing this:

→ → → → → → Backspace Backspace Backspace

you can simply use:

dw

Or instead of selecting text with a mouse, you can use:

ci"

to change everything inside quotation marks.

Once these commands become muscle memory, editing configuration files over SSH becomes much faster.

See also: Mastering the Linux Command Line — Your Complete Free Training Guide

Let’s go beyond i and :wq.


First: Understand the Vi Mental Model

Before learning advanced commands, understand the basic idea behind Vi.

Vi has different modes.

The two you’ll use most are:

Normal mode
Insert mode

When Vi starts, you’re normally in Normal mode.

Press:

i

and you enter Insert mode.

Press:

Esc

and you’re back in Normal mode.

The important thing is that most advanced Vi commands are designed to be used from Normal mode.

For example:

dw

means:

d + w

where:

d = delete
w = move forward by a word

This gives you a very useful formula:

operator + motion

Once you understand this, many Vi commands stop looking random.


1. Move Faster Than the Arrow Keys

You can use the arrow keys, but Vi’s movement commands are much more powerful.

Basic movement:

h   left
j   down
k   up
l   right

But you can also jump by words.

w

moves to the beginning of the next word.

b

moves backward to the beginning of the previous word.

e

moves to the end of the current or next word.

For example:

The PostgreSQL server is running normally
    ^

Press:

w

and the cursor jumps to:

The PostgreSQL server is running normally
        ^

Instead of pressing the right arrow repeatedly, you’re moving semantically.


2. Jump to the Beginning or End of a Line

These are commands you’ll use constantly.

0

moves to the absolute beginning of the line.

^

moves to the first non-whitespace character.

$

moves to the end of the line.

For example:

        server_name nginx.example.com;
        ^

Press:

^

and the cursor moves to:

        server_name nginx.example.com;
        ^

the s.

Press:

$

and it jumps to:

        server_name nginx.example.com;
                                      ^

This is particularly useful when editing configuration files with indentation.


3. Delete With Motions

Here’s where Vi becomes interesting.

The d command means:

delete

Combine it with a movement command.

For example:

dw

means:

Delete from here to the next word.

Similarly:

de

deletes to the end of the word.

d$

deletes from the cursor to the end of the line.

And:

d0

deletes from the cursor to the beginning of the line.

For example:

server_name old-server.example.com;
            ^

Place the cursor before old-server and run:

d$

Everything from the cursor to the end of the line is removed.


4. Delete an Entire Line

You don’t need to select the entire line.

Simply use:

dd

For example:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
}

Put the cursor anywhere on:

    listen 80;

and press:

dd

The entire line disappears.

This is one of the first commands worth memorizing.


5. Delete Multiple Lines

You can combine numbers with commands.

For example:

5dd

means:

Delete five lines.

Similarly:

3dw

deletes three words.

And:

2dd

deletes two lines.

This pattern is incredibly useful:

number + command

For example:

10j

moves down ten lines.

5w

moves forward five words.

3dd

deletes three lines.


6. Undo and Redo

Made a mistake?

Use:

u

to undo.

Need to redo the change?

Use:

Ctrl-r

For example:

dd

deletes a line.

Then:

u

brings it back.

Then:

Ctrl-r

applies the deletion again.

A simple workflow is:

make change
    |
    v
check result
    |
    +--> wrong? --> u
    |
    +--> correct? --> continue

7. Change Instead of Delete

The c command means:

change

It’s similar to delete, except Vi puts you into Insert mode afterward.

For example:

cw

means:

Change the current word.

Suppose you have:

server_name old-server.example.com;
            ^

Use:

cw

Then type:

new-server.example.com

and press:

Esc

You have replaced the word without manually deleting it first.


8. Change the Rest of a Line

This is extremely useful:

c$

It means:

Change from the cursor to the end of the line.

For example:

server_name old-server.example.com;
            ^

Press:

c$

Then type:

new-server.example.com;

and press Esc.

This is often faster than:

d$
i

9. Change an Entire Line

Use:

cc

or:

S

Both can change the current line.

For example:

listen 80;

Press:

cc

Then type:

listen 8080;

and press:

Esc

The indentation is generally preserved more conveniently than manually deleting the line.


10. The Power of Text Objects

This is where Vi really starts to feel different from conventional editors.

Consider:

server_name "old-server.example.com";

Suppose you want to replace only the text inside the quotes.

You could move the cursor around manually.

Or use:

ci"

Break it down:

c

change

i"

inside quotes

So:

ci"

means:

Change the text inside the quotation marks.

Type:

new-server.example.com

and press:

Esc

Now you have:

server_name "new-server.example.com";

That’s much faster.


11. Common Text Objects

Some useful text objects are:

iw    inner word
aw    a word
i"    inside double quotes
a"    around double quotes
i'    inside single quotes
a'    around single quotes
i(    inside parentheses
a(    around parentheses
i[    inside brackets
a[    around brackets
i{    inside braces
a{    around braces

For example:

echo "hello world"

Put the cursor anywhere inside:

hello world

Then:

ci"

changes the contents.

With:

di"

you delete the contents.

With:

yi"

you copy the contents.

The pattern is:

operator + text object

For example:

d + i"
c + i(
y + i{

Once you recognize this pattern, a lot of Vi becomes predictable.


12. Delete Inside Parentheses

Suppose you have:

systemctl restart nginx --no-block

Or a programming example:

connect(host="db01", port=5432)

Put the cursor inside the parentheses and use:

di(

The contents disappear.

If you want to remove the parentheses too:

da(

This distinction is important:

di(

means:

delete inside parentheses

while:

da(

means:

delete around parentheses


13. Change Text Inside Quotes

This is one of my favorite practical Vi commands.

Suppose you have:

DATABASE_HOST="old-db.example.com"

Put the cursor anywhere inside the quoted value:

ci"

Type:

new-db.example.com

Press:

Esc

Done.

No mouse.

No Shift+Arrow.

No repeated Backspace.


14. Find a Character With f

Suppose you have:

server_name web01.example.com;

You want to jump to the first ;.

Use:

f;

The cursor jumps directly to the semicolon.

Similarly:

ft

moves forward until the character before the next t.

You can repeat the search with:

;

and go backward with:

,

This becomes particularly powerful when combined with operators.

For example:

d;

can delete from the current position through the next occurrence of the searched character, depending on the motion context.


15. Find a Character Without Moving Onto It

There is another useful command:

t

For example:

t;

means:

Move until just before the next ;.

This is useful when you want to operate on text but keep the delimiter.

For example:

dt;

means:

Delete until the next semicolon, but don’t delete the semicolon itself.

This is a very useful pattern when editing configuration lines.


16. Jump Between Matching Brackets

Suppose you have:

if (server_status == "ready") {
    start_service();
}

Put the cursor on:

(

and press:

%

Vi jumps to the matching:

)

The same works with:

()
[]
{}

This is extremely useful when editing code or complex configuration files.

For example:

location /api/ {
    proxy_pass http://backend;
}

Place the cursor on { and press:

%

Vi jumps to the corresponding }.


17. Search for Text

Use:

/pattern

For example:

/server_name

Press Enter.

Vi jumps to the next occurrence.

To find the next match:

n

To find the previous match:

N

This is much faster than scrolling through a large configuration file.

For example:

/Listen

can quickly take you to the relevant section of a large sshd_config.


18. Search and Replace

One of the most useful Vi commands for Linux administrators is substitution.

The basic syntax is:

:s/old/new/

For example:

:s/oldhost/newhost/

replaces the first matching occurrence on the current line.

To replace every occurrence on the current line:

:s/oldhost/newhost/g

To replace throughout the entire file:

:%s/oldhost/newhost/g

This is much faster than manually editing dozens of lines.


19. Replace With Confirmation

Before performing a large replacement, you can ask Vi to confirm each change.

Use:

:%s/oldhost/newhost/gc

The c means:

confirm

Vi will ask you whether each match should be changed.

This is useful when the same text appears in multiple contexts and you don’t want to blindly replace everything.


20. Replace Only on Specific Lines

You don’t always need to modify the entire file.

For example:

:10,20s/old/new/g

means:

Replace old with new between lines 10 and 20.

You can also use:

:1,10s/foo/bar/g

for the first ten lines.

And:

:.,$s/foo/bar/g

means:

Replace from the current line to the end of the file.


21. Copy and Paste With Yank

In Vi, copying is usually called yanking.

The command is:

y

For example:

yy

copies the current line.

Then:

p

pastes after the current line.

And:

P

pastes before the current line.

For example:

server {
    listen 80;
}

Put the cursor on:

listen 80;

Press:

yy

Then:

p

You get:

server {
    listen 80;
    listen 80;
}

22. Move Lines With dd and p

Here’s a surprisingly useful trick.

Suppose you have:

line 1
line 2
line 3

Put the cursor on:

line 1

Run:

dd

Then move to line 3 and press:

p

The line can be moved around the file.

So:

dd
p

isn’t only for deleting and pasting.

It’s also a simple way to move lines.


23. Copy Multiple Lines

Use a count:

3yy

This yanks three lines.

Then:

p

pastes them.

Similarly:

5dd

deletes five lines.

The count syntax makes bulk editing much faster.


24. Visual Mode

Sometimes you really do want to select text.

Vi provides Visual mode.

Character selection:

v

Line selection:

V

Block selection:

Ctrl-v

These are three different tools.

For example:

v

lets you select individual characters.

V

selects entire lines.

And:

Ctrl-v

creates a rectangular block.


25. Visual Block Mode Is Extremely Useful

Suppose you have:

server1  10.10.1.10
server2  10.10.1.11
server3  10.10.1.12
server4  10.10.1.13

You want to add:

prod-

to the beginning of several lines.

Press:

Ctrl-v

Select the vertical block.

Then:

I

Type:

prod-

Then press:

Esc

Vi inserts the text across the selected lines.

This is one of the features that makes Vi incredibly useful for structured configuration files.


26. Repeat the Last Change With .

The dot command:

.

repeats your last change.

This sounds simple, but it can save a huge amount of time.

Suppose you change:

server1

to:

web01

Then move to another occurrence and press:

.

Vi repeats the previous editing operation.

For repetitive changes:

make one change
move
.
move
.
move
.

This is often much faster than repeating the entire command sequence.


27. The Dot Command Is a Big Productivity Booster

Consider:

server_name app01;
server_name app02;
server_name app03;
server_name app04;

You change one line using:

cw

Then type the new value.

After that, move to the next matching location and press:

.

You can repeat the same operation.

The key is to make your first edit in a way that can be repeated cleanly.

That’s one reason experienced Vi users often think about:

“How can I make this change repeatable?”

rather than:

“How do I edit this one line?”


28. Record a Macro

If the same sequence needs to be performed many times, use a macro.

Start recording into register a:

qa

Perform your commands.

Then stop recording:

q

Replay it with:

@a

For example:

qa

perform:

dd

then:

q

Now:

@a

repeats the recorded operation.

You can repeat the macro with:

@@

which runs the last executed macro again.


29. Registers: Vi’s Clipboard System

Vi doesn’t have just one clipboard.

It has registers.

For example:

"ayy

means:

Yank the current line into register a.

Then:

"ap

pastes from register a.

This is useful when you need to copy several different pieces of text without overwriting your previous yank.

You can inspect registers with:

:reg

This can show named registers, the unnamed register, search history, and other stored information.


30. The System Clipboard

Depending on how Vim was built, you may also have access to the system clipboard.

Check:

vim --version | grep clipboard

You might see:

+clipboard

or:

-clipboard

If clipboard support is available, commands such as:

"+yy

can yank a line into the system clipboard.

And:

"+p

can paste from it.

This is particularly useful when working over SSH or inside terminal environments.


31. Jump to a Specific Line

Need to go directly to line 500?

Use:

:500

Or:

500G

Both can take you to a specific line.

You can also use:

gg

to jump to the beginning of the file.

And:

G

to jump to the end.

These commands are extremely useful for large configuration files.


32. Jump Half a Screen at a Time

For large files, you don’t always want to scroll one line at a time.

Useful commands include:

Ctrl-d

scroll down roughly half a screen.

Ctrl-u

scroll up roughly half a screen.

Ctrl-f

page forward.

Ctrl-b

page backward.

And:

zz

centers the current line on the screen.

That last one is particularly useful after searching.


33. Join Lines

Suppose you have:

server_name
example.com;

Put the cursor on the first line and press:

J

The lines are joined:

server_name example.com;

This is useful when cleaning up wrapped configuration or text.


34. Replace a Single Character

Use:

r

followed by a character.

For example:

rx

replaces the current character with x.

This is different from:

cw

because you don’t enter Insert mode.

For example:

port=5433

If the cursor is on 3 and you want 2:

r2

Done.


35. Replace Multiple Characters

The R command enters Replace mode.

R

Then you can type replacement characters continuously.

Press:

Esc

when you’re done.

This is useful when replacing a sequence of characters without inserting new text.


36. Indent Multiple Lines

Select lines using Visual mode:

V

Then:

>

to indent.

Use:

<

to remove indentation.

You can also repeat the indentation with:

>>

for the current line.

And:

<<

to decrease indentation.

This is especially useful when editing scripts or configuration files.


37. Auto-Indent

For a selected block, you can use:

=

to auto-indent.

For example:

V

select several lines, then:

=

Depending on the file type and Vim configuration, Vim can adjust indentation automatically.

For a whole file:

gg=G

This means:

gg    go to beginning
=     indent
G     through the end

It’s a surprisingly useful command.


38. Edit Multiple Files

Vi can also work with multiple files.

For example:

vim file1.conf file2.conf file3.conf

You can move between buffers with:

:next

and:

:previous

You can see open buffers with:

:buffers

Then switch to a buffer:

:buffer 2

This is useful when comparing or editing several related configuration files.


39. Split the Screen

Open another file in a horizontal split:

:split file2.conf

Or vertically:

:vsplit file2.conf

Move between windows with:

Ctrl-w h
Ctrl-w j
Ctrl-w k
Ctrl-w l

For example:

+-------------------------+-------------------------+
|                         |                         |
|     nginx.conf          |     upstream.conf       |
|                         |                         |
|                         |                         |
+-------------------------+-------------------------+

This is much more convenient than constantly opening and closing files.


40. Compare Two Files

Vim can also be used for side-by-side comparison.

For example:

vimdiff old.conf new.conf

You’ll get a split view showing differences between the files.

This is particularly useful for configuration changes:

vimdiff /etc/ssh/sshd_config \
        /etc/ssh/sshd_config.backup

Instead of manually comparing two large files, Vim highlights the differences.


41. A Practical SSH Configuration Example

Suppose you’re editing:

sudo vi /etc/ssh/sshd_config

You want to find:

PasswordAuthentication

Instead of scrolling:

/PasswordAuthentication

Press Enter.

Then:

n

to find the next match.

Suppose you find:

PasswordAuthentication yes

Move to yes and use:

cw

Type:

no

Then:

Esc

Now:

PasswordAuthentication no

Save:

:w

Validate the configuration before restarting SSH:

sudo sshd -t

Then restart the service if appropriate:

sudo systemctl restart sshd

This is a much more realistic workflow than memorizing isolated Vi commands.


42. Another Real Example: Editing PostgreSQL Configuration

Suppose you’re editing:

sudo vi /var/lib/pgsql/data/postgresql.conf

You need to change:

max_connections = 100

to:

max_connections = 500

Search:

/max_connections

Then move to the value and use:

cw

Type:

500

Press:

Esc

If you need to make the same style of change elsewhere, the dot command can often repeat your last edit.

For a known global replacement, you could instead use:

:%s/max_connections = 100/max_connections = 500/g

The important skill is knowing which editing method fits the task.


43. A Practical Log File Example

Suppose you’re investigating a large log file:

vi /var/log/messages

You want to find an error:

/ERROR

Then:

n

to move between errors.

If you find something interesting, mark the location:

ma

This creates mark a.

You can continue exploring the file.

Later:

'a

takes you back to that location.

Marks are useful when investigating large configuration files or logs.


44. Marks Are Easy to Overlook

You can create multiple marks:

ma
mb
mc

Then jump back:

'a
'b
'c

For example:

ma

at the beginning of a configuration section.

Search elsewhere.

Then:

'a

to return.

It’s a small feature, but very useful during troubleshooting.


45. Use Numbers With Almost Everything

One of the easiest ways to become faster in Vi is to stop repeating commands manually.

Instead of:

j
j
j
j
j

use:

5j

Instead of:

dd
dd
dd

use:

3dd

Instead of:

w
w
w

use:

3w

The general pattern is:

[count][command]

This is one of the fundamental ideas behind Vi’s command language.


46. The Real Power: Combining Commands

The best Vi users don’t necessarily memorize hundreds of commands.

They understand how commands combine.

For example:

d$

means:

delete + move to end of line
ci"

means:

change + inside quotes
da(

means:

delete + around parentheses
yap

means:

yank + a paragraph

Once you learn the building blocks, you can construct commands instead of memorizing them individually.


Advanced Vi Command Cheat Sheet

CommandAction
wNext word
bPrevious word
eEnd of word
0Beginning of line
^First non-whitespace character
$End of line
ggBeginning of file
GEnd of file
nNext search match
NPrevious search match
%Matching bracket
f<char>Find character
t<char>Move before character
ddDelete line
dwDelete word
d$Delete to end of line
ccChange line
cwChange word
c$Change to end of line
ci"Change inside quotes
di(Delete inside parentheses
da(Delete around parentheses
yyYank line
pPaste after
PPaste before
uUndo
Ctrl-rRedo
.Repeat last change
vVisual character mode
VVisual line mode
Ctrl-vVisual block mode
JJoin lines
r<char>Replace one character
RReplace mode
>Indent
<Unindent
gg=GAuto-indent file
qa ... qRecord macro in register a
@aRun macro a
:s/old/new/Replace on current line
:%s/old/new/gReplace throughout file
:wSave
:qQuit
:wqSave and quit

The Commands Worth Learning First

You don’t need to memorize the entire table.

If you’re currently comfortable with:

i
Esc
:w
:q
:wq

start with these:

w
b
e
0
$
dd
dw
cw
ci"
di(
yy
p
u
Ctrl-r
.
/
n
%
gg
G

Then learn:

f
t
V
Ctrl-v
:
%s
macros
registers

That’s enough to dramatically change how you edit files.


Final Thoughts

Vi becomes much more interesting once you stop treating it like a keyboard-controlled version of a GUI editor.

The real idea is:

operator + motion

and:

operator + text object

For example:

dw

Delete a word.

c$

Change to the end of the line.

ci"

Change inside quotes.

di(

Delete inside parentheses.

yap

Copy a paragraph.

Then add:

count

when you need to repeat something:

5dd
3w
10j

And when you’ve found a useful editing sequence:

.

repeats it.

That’s the point where Vi starts to feel less like an old-fashioned editor and more like a small language for manipulating text.

You don’t need to learn everything at once.

Start with:

w  b  0  $  dd  cw  ci"  yy  p  u  .  /  n

Use them every day.

After a while, you’ll find yourself making changes in a few keystrokes that previously required a mouse, multiple selections, and a lot of backspacing.

Avatar photo
David Cao

David is a Cloud & DevOps Enthusiast. He has years of experience as a Linux engineer. He had working experience in AMD, EMC. He likes Linux, Python, bash, and more. He is a technical blogger and a Software Engineer. He enjoys sharing his learning and contributing to open-source.

Articles: 737

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *