Working Code
Imagine this code is open in Vim:
const userName = "Alice";
const userAge = 25;
const userEmail = "alice@example.com";
function getUserName() {
return userName;
}
function getUserAge() {
return userAge;
}
Type /user and press Enter — the cursor jumps to the first occurrence of user in the file. Press n for the next result, N for the previous one.
Now type :%s/user/account/g and press Enter. Every user in the entire file becomes account.
Try It Yourself
Paste the code above into Vim and try:
- Type
/userNameto find the firstuserName. - Press
nrepeatedly to cycle through everyuserName. - Press
*to search for the word under the cursor instantly.nstill cycles through results. - Type
:%s/userName/accountName/gcto confirm each replacement one by one.- Press
yto replace,nto skip.
- Press
"Why?"
Search
| Command | Action |
|---|---|
/pattern | Search downward |
?pattern | Search upward |
n | Next result in the same direction |
N | Next result in the opposite direction |
* | Search for word under cursor (downward) |
# | Search for word under cursor (upward) |
* is especially useful. Put the cursor on a variable name, press *, and you instantly see everywhere that variable appears.
Search highlights
Highlighting matches makes them easy to spot:
:set hlsearch " turn on search highlighting
:nohlsearch " turn off current highlight (short: :noh)
:set nohlsearch " disable highlighting feature entirely
:noh only dismisses the current highlight temporarily. The next search highlights again. Add :set hlsearch to your config file to keep it always on.
Substitute
The basic substitute command looks like this:
:[range]s/pattern/replacement/[flags]
Range:
| Range | Meaning |
|---|---|
| (none) | Current line only |
% | Entire file |
1,10 | Lines 1 through 10 |
'<,'> | Current Visual-mode selection |
Flags:
| Flag | Meaning |
|---|---|
g | Replace every match in the line (default: first match only) |
c | Confirm each replacement |
i | Case-insensitive |
Real-world examples
:s/foo/bar/ " replace first foo on current line with bar
:s/foo/bar/g " replace every foo on current line with bar
:%s/foo/bar/g " replace every foo in the file with bar
:%s/foo/bar/gc " confirm each replacement in the whole file
:%s/foo/bar/gi " case-insensitive substitute across the file
:5,20s/foo/bar/g " substitute only on lines 5-20
Choices in confirm mode (c flag)
With gc, you choose what to do at each match:
| Key | Action |
|---|---|
y | Replace this match |
n | Skip this match |
a | Replace this and all remaining |
q | Quit substituting |
l | Replace this one and quit |
Search combined with operators
You can use a search as a motion too:
d/function → delete up to (but not including) "function"
c/end → delete up to "end" and enter Insert mode
Deep Dive
Regex basics
Vim search supports regular expressions. A few common patterns:
/\d\+ " one or more digits
/\<word\> " exactly "word" (no partial matches)
/^const " lines starting with const
/;$ " lines ending with ;
When you press *, Vim automatically wraps the search in \<word\> so only whole-word matches are found.
Rename a variable
Rename data to response in this code:
function fetchData() {
const data = fetch("/api/users");
const dataList = data.json();
console.log("data loaded:", dataList);
return data;
}
Step 1: Use * to find all uses of data.
Step 2: Run :%s/data/response/gc and confirm each one.
Watch out: should dataList change too? What about "data loaded:"? The gc flag lets you decide selectively.
Challenge: Try :%s/\<data\>/response/gc for whole-word matching.
question: "What does % mean in :%s/old/new/g?" options:
question: "Which key searches instantly for the word under the cursor?" options:
question: "What does the c flag do in :%s/foo/bar/gc?" options: