search
:s and :%s
Substitute (find-and-replace) within a range of lines. Without a range :s works on the current line only; :%s uses % as shorthand for the whole file (equivalent to :1,$s). Add flags like g (all matches per line) and c (confirm).
:[range]s/{pattern}/{replacement}/[flags] :%s/…/g (command mode) Variations
| Keystroke | Effect |
|---|---|
| g | All occurrences on each line (not just the first) |
| c | Confirm each replacement (y/n/a/q/l) |
| i | Case-insensitive for this substitution |
| % | Range shorthand for the whole file (:%s = :1,$s) |
| '<,'> | Range that means 'the last visual selection' |
Examples
:s/foo/bar/ Replace first foo with bar on current line
:%s/foo/bar/g Replace every foo with bar in the whole file
:%s/\s\+$// Strip trailing whitespace from every line
:%s/foo/bar/gc Interactive replace across file, confirm each match
Gotcha
Without the g flag only the FIRST match per line is replaced — a classic 'why didn't it work' moment. Note: % here means 'whole file', but the SAME % key in normal mode jumps to a matching bracket — mode context matters.
Related
/ and ?
/ searches forward for a regex, ? searches backward. After the search, press n to jump to the next match and N for the previous — searching is a first-class motion, so d/foo deletes up to the next 'foo'.
* / #
* searches forward for the whole word under the cursor; # searches backward. Zero typing needed — put your cursor on the identifier and hit *.
%
In normal mode, % jumps between matching pairs of (), [], {}, and (with matchit) HTML/XML tags. Indispensable for navigating nested code and confirming that a stray brace really does close where you think it does.
n / N
n jumps to the next match of the last search, N to the previous. Direction is relative to the ORIGINAL search direction — if you searched with ?, then n goes backward.