DaleSchool

Search and Replace

Beginner15min

Learning Objectives

  • Search with / and ?
  • Jump through results with n and N
  • Replace with :%s/old/new/g
  • Search for the word under the cursor instantly with *

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:

  1. Type /userName to find the first userName.
  2. Press n repeatedly to cycle through every userName.
  3. Press * to search for the word under the cursor instantly. n still cycles through results.
  4. Type :%s/userName/accountName/gc to confirm each replacement one by one.
    • Press y to replace, n to skip.

"Why?"

Search

CommandAction
/patternSearch downward
?patternSearch upward
nNext result in the same direction
NNext 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:

RangeMeaning
(none)Current line only
%Entire file
1,10Lines 1 through 10
'<,'>Current Visual-mode selection

Flags:

FlagMeaning
gReplace every match in the line (default: first match only)
cConfirm each replacement
iCase-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:

KeyAction
yReplace this match
nSkip this match
aReplace this and all remaining
qQuit substituting
lReplace 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: