level 11
Search & Replace
The substitute command and regex for surgical edits.
:s is a tiny find-and-replace language living inside your editor. Full regular expressions, surgical control over scope, optional confirm-each-one prompting. When a rename is too irregular for n . and too big to do by hand, this is the tool. It looks cryptic for five minutes, then becomes the thing you miss in every editor that doesn’t have it.
The Substitute Command
:s/old/new/ → first match on the current line
:s/old/new/g → all matches on the current line
:%s/old/new/g → all matches in the whole file
:%s/old/new/gc → file-wide, confirm each one
The g flag means “all on the line”; % means “the whole file”; c prompts for confirmation (y to replace, n to skip, q to quit).
Regex Patterns
\<word\> → exact word (word boundaries)
\d\+ → one or more digits
^import → lines starting with "import"
};$ → lines ending with "};"
Vim uses its own regex flavor: \+ means “one or more” (note the backslash), \d is a digit, \< and \> are word boundaries, ^ and $ anchor line start and end.
Heads up about the editor below. Real Vim and Neovim use the flavor above. The embedded editor here runs on CodeMirror, which uses JavaScript regular expressions — so in these exercises drop the backslash on quantifiers (
\d+, not\d\+), use(...)for groups, and$1$2for backreferences. The:%s/old/new/flagsstructure is identical; only the pattern dialect changes. Where the real-Vim form differs, it’s noted inline.
\d+ (here) → \d\+ (real Vim) one or more digits
(\w+) (here) → \(\w\+\) (real Vim) a capture group
$1 (here) → \1 (real Vim) reuse a captured group
& (both) the whole match
Substitute on a line
- Type
:s/cat/dog/and Enter — only the firstcatchanges. - Undo. Type
:s/cat/dog/g— all of them on the line change. - Undo. Type
:s/the/a/g.
goal Without g, only the first match per line changes.
File-wide substitution
- Type
:%s/user/member/g— everyuserchanges, including insideuserIdandgetUser. - Undo. Type
:%s/User/Member/g— only the capitalized form changes.
goal %s reaches every line; mind partial matches.
Confirm each replacement
- Type
:%s/timeout/delay/gc. - Press
yto accept,nto skip, stepping through each prompt. - Verify only the ones you accepted changed.
goal Use the c flag for selective, not blind, replacement.
Regex patterns
- Replace
user+ digits withmember::%s/user\d+/member/g. (Real Vim:\d\+.) - Undo. Replace lines starting with
admin::%s/^admin\d+/superuser/g. - Undo. Replace the last word of each line:
:%s/\w+$/ACTION/g.
goal Use the \d digit class, anchors, and word boundaries to target precisely.
Real-world refactor
- Rename the class:
:%s/UserProfile/MemberCard/g. - Rename the field:
:%s/userData/memberData/g. - Rename the flag:
:%s/userLoading/isLoading/g.
goal One command per rename — the power of :s for large edits.
Capstone — capture groups and the whole-match &
A plain replace can only swap fixed text. Capture groups let you grab pieces of each match and rearrange them. Wrap part of the pattern in (...), then reference what you caught with $1, $2. & is the whole match.
- Flip every name to
Last, First::%s/(\w+) (\w+)/$2, $1/. Group 1 is the first name, group 2 the last; the replacement reorders them. (Real Vim:\(\w\+\) \(\w\+\)with\1\2.) - Undo with
u. Now quote each entire line using the whole match::%s/.+/"&"/—&stands in for everything the pattern matched. - Undo. Do both at once — reorder and quote:
:%s/(\w+) (\w+)/"$2, $1"/.
goal Reorder and wrap text by reusing what the pattern captured.