C.W.K.
Stream
Lesson 04 of 06 · published

Searching and Replacing

~13 min · vim, search, substitute, regex

Level 0Trapped
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Search is also a motion

You already know /pattern finds the next match. The magic is that searches compose with operators: d/foo<Enter> deletes everything from the cursor up to the next "foo." Search is a verb-chain ingredient, not a separate tool.

The basic search keys

  • /pattern — search forward for a regex.
  • ?pattern — search backward.
  • n — next match (same direction as last search).
  • N — previous match.
  • * — search forward for the word under the cursor.
  • # — search backward for the word under the cursor.
  • :noh — clear the search highlighting (or map <Esc> to it; see Track 4).

The substitute command

Vim's :s is a regex search-and-replace, with flags that matter:

  • g — global within a line (every occurrence, not just first).
  • c — confirm each replacement (great for risky changes).
  • i — case-insensitive.
  • I — case-sensitive (overrides ignorecase).

Range matters

:s/a/b/ replaces only on the current line. :%s/a/b/g uses % as "the whole file." :'<,'>s/a/b/g uses the visual selection. :5,20s/a/b/g uses lines 5 through 20. Range first, command second — that's the recipe.

Magic, very magic, and escape soup

Vim regexes are notoriously punctuation-heavy because by default many metacharacters need backslashes. \v at the start of a pattern enables "very magic" mode where regexes look like everywhere else: (, +, ? work without backslashes. Habit: start every nontrivial regex with \v.

Replay the last substitute. & in Normal mode repeats the last :s on the current line. g& repeats it across the whole file. Pair with the dot command's logic — search/substitute have their own repeat keys.

Code

Search basics·vim
/pattern<Enter>    " search forward
?pattern<Enter>    " search backward
n                  " next match (same direction)
N                  " next match (opposite direction)
*                  " forward search for word under cursor
#                  " backward search for word under cursor
:noh               " clear search highlight
:set hlsearch ic   " highlight search + ignore case (you'll want both)
Substitute — the canonical pattern·vim
:s/old/new/         " replace first match on this line
:s/old/new/g        " all matches on this line
:%s/old/new/g       " all matches in the file
:%s/old/new/gc      " with confirmation (y/n/a/q)
:'<,'>s/old/new/g   " all matches in the visual selection
:5,20s/old/new/g    " all matches on lines 5 through 20
:g/TODO/d           " delete every line containing TODO
Very-magic regex — the fix for backslash soup·vim
:%s/\v(\w+) (\w+)/\2 \1/g    " swap two adjacent words
:%s/\v\s+$//                       " strip trailing whitespace
:%s/\v^\s+//                       " strip leading whitespace
:%s/\v(foo|bar|baz)/X/g            " alternation without escapes
:%s/\v(\d+)\.(\d+)/\2.\1/g    " swap parts around a dot

External links

Exercise

Open a source file. Do these substitutions, each with gc to feel the confirmation prompt: (1) rename one variable globally, (2) strip trailing whitespace from the whole file with :%s/\v\s+$//, (3) swap the order of two words on every line of a small block using a very-magic capture-group substitution. If the regex feels wrong, undo and read it slowly — capture groups are the part everyone gets wrong on the first try.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.