Skip to main content

Vim Search, Replace, and Navigation

·933 words·5 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.
vim-essentials - This article is part of a series.
Part 3: This Article

Searching
#

Forward and backward search#

/pattern     Search forward
?pattern     Search backward

Press Enter to execute the search, then:

KeyAction
nNext match (same direction)
NPrevious match (opposite direction)

Search for the word under the cursor
#

KeyAction
*Search forward for the exact word under cursor
#Search backward for the exact word under cursor

These match whole words — searching on port won’t match export.

Search options
#

" Case-insensitive search (add \c to any pattern)
/error\c

" Case-sensitive search (add \C to any pattern)
/Error\C

" Enable incremental search (highlights as you type)
:set incsearch

" Highlight all matches
:set hlsearch

" Clear current highlights
:nohlsearch
" or shorthand
:noh

Search and Replace (Substitution)
#

The substitution command follows this format:

:[range]s/pattern/replacement/[flags]

Common substitutions
#

CommandEffect
:s/old/new/Replace first occurrence on current line
:s/old/new/gReplace all occurrences on current line
:%s/old/new/gReplace all occurrences in the entire file
:%s/old/new/gcReplace all, but ask for confirmation each time
:5,10s/old/new/gReplace on lines 5 through 10
:'<,'>s/old/new/gReplace within visual selection

Flags
#

FlagMeaning
gGlobal — all matches on the line, not just the first
cConfirm each replacement
iCase-insensitive
ICase-sensitive
nCount matches without replacing

Confirmation prompts
#

With the c flag, Vim asks for each match:

KeyAction
yReplace this match
nSkip this match
aReplace all remaining
qQuit substitution
lReplace this one and quit

Regex Basics in Vim
#

Vim uses its own regex flavor. A few things to know:

Characters that need escaping
#

In Vim’s default “magic” mode, these are literal unless escaped:

To matchType
( group )\( and \)
+ (one or more)\+
? (zero or one)\?
`` (or)
{n,m} (quantifier)\{n,m\}

These work without escaping: . * ^ $ []

Very magic mode
#

Prefix with \v to make all special characters work like standard regex (no escaping parens, plus, etc.):

" Standard Vim regex — escape everything
:%s/\(foo\|bar\)\+/replacement/g

" Very magic — cleaner
:%s/\v(foo|bar)+/replacement/g

Useful patterns
#

" Delete trailing whitespace
:%s/\s\+$//g

" Delete blank lines
:g/^$/d

" Add a semicolon to the end of every line
:%s/$/;/

" Replace multiple spaces with a single space
:%s/ \+/ /g

" Swap two words: foo bar → bar foo
:%s/\(foo\) \(bar\)/\2 \1/g

Capture groups and backreferences
#

Use \( and \) to capture, \1, \2, etc. to reference:

" Wrap each word in quotes
:%s/\(\w\+\)/"\1"/g

" Swap first and last name
:%s/\(\w\+\) \(\w\+\)/\2 \1/g

The Global Command
#

:g executes a command on every line matching a pattern:

" Delete all lines containing "debug"
:g/debug/d

" Delete all blank lines
:g/^$/d

" Move all TODO comments to end of file
:g/TODO/m$

" Indent all lines containing "return"
:g/return/>

The inverse — act on lines that don’t match:

" Delete all lines NOT containing "keep"
:v/keep/d
" equivalent to
:g!/keep/d

Jumping Between Locations
#

Jump list
#

Vim tracks where you’ve been. Navigate your history:

KeyAction
Ctrl-oJump back (older position)
Ctrl-iJump forward (newer position)

Searches, gg, G, and other big moves add to the jump list. Small moves like j, k, w don’t.

" View the jump list
:jumps

Matching brackets
#

KeyAction
%Jump to matching bracket: (), {}, []

Works for parentheses, braces, brackets, and with some plugins, HTML tags.

Line jumps
#

CommandAction
42G or :42Go to line 42
ggGo to first line
GGo to last line
HTop of visible screen
MMiddle of visible screen
LBottom of visible screen

Marks
#

Marks save a position you can return to later.

Setting marks
#

ma      Set mark 'a' at current position
mb      Set mark 'b' at current position

Lowercase marks (az) are local to the file. Uppercase marks (AZ) are global across files.

Jumping to marks
#

CommandJumps to
'aLine of mark a (first non-blank character)
`aExact position of mark a (line and column)
''Previous position (before last jump)
``Exact previous position

Special marks
#

MarkPosition
'.Last change
'^Last insert
'[ and ']Start/end of last yank or change
'< and '>Start/end of last visual selection
" List all marks
:marks

Practical Workflows
#

Find and replace a variable name with confirmation
#

:%s/oldName/newName/gc

Review each occurrence and press y or n.

Jump between function definitions
#

/^function     (search for functions at start of line)
n              (next match)
n              (keep going)

Use marks to bounce between two locations
#

ma             (mark current position as 'a')
               ...navigate elsewhere...
mb             (mark this position as 'b')
'a             (jump back to mark a)
'b             (jump back to mark b)

Delete all lines matching a pattern
#

:g/console\.log/d

Operate on search results with gn
#

gn selects the next search match. Combined with operators:

/pattern       (search for something)
cgn            (change the next match)
               ...type replacement...
Esc
.              (dot repeats — changes next match)
.              (and again)

This is one of the fastest ways to rename something selectively.

Best Practices
#

  • Use * and # to quickly search for the word under your cursor — faster than typing it out
  • Use :noh (or map it to a key) to clear search highlights after you’re done
  • Prefer \v (very magic) for complex regex to avoid escaping everything
  • Use gn + dot for selective replacements — more control than :%s///gc when you only need a few
  • Set marks at locations you return to frequently — they’re faster than searching each time
  • Use Ctrl-o liberally — it always takes you back to where you were
vim-essentials - This article is part of a series.
Part 3: This Article