Search and Replace

Summary: in this tutorial, you will learn master vim's powerful search, substitute, and global commands to find and replace text across your files with precision.

Search and Replace

Searching is one of the fastest ways to navigate and edit files. Vim's search features go far beyond a simple "Find and Replace" dialog — you can search with patterns, replace text across an entire file in one command, and run commands on every matching line.

What you'll learn in this tutorial:

  • How to search forward and backward through a file
  • How to move between search results
  • How to search and replace text (single occurrence or all at once)
  • How to use simple patterns to match flexible text
  • How to use the powerful :global command to act on every matching line
  • Useful search settings that make your life easier

Basic Searching

Searching Forward

To search for text in Vim, press / (forward slash) from Normal mode, type what you're looking for, and press Enter:

/hello        " Search forward for the text "hello"

Here's what happens step by step:

  1. Press / — a cursor appears at the bottom of the screen
  2. Type the text you want to find (e.g., hello)
  3. Press Enter — your cursor jumps to the first match
  4. If there are multiple matches, keep reading to learn how to cycle through them

Searching Backward

Use ? instead of / to search backward (toward the beginning of the file):

?hello        " Search backward for "hello"

Moving Between Matches

After you've searched for something, use these keys to jump between matches:

KeyWhat It Does
nJump to the next match (in the direction you searched)
NJump to the previous match (opposite direction)

So if you searched forward with /hello:

  • n moves forward to the next "hello"
  • N moves backward to the previous "hello"

If you searched backward with ?hello:

  • n moves backward (the direction of your search)
  • N moves forward

Quick way to search for a word: Put your cursor on any word and press * (asterisk). Vim instantly searches forward for that exact word. Press # to search backward. This is extremely useful for finding all uses of a variable name or function name — just put your cursor on it and press *.

Search Settings (Make Searching Easier)

Add these settings to your ~/.vimrc file to make searching much more pleasant. If you followed the installation tutorial, you may already have some of these:

set incsearch      " Show matches as you type (don't wait for Enter)
set hlsearch       " Highlight ALL matches in the file
set ignorecase     " Searches are case-insensitive by default
set smartcase       " ...BUT become case-sensitive if you type a capital letter

What do these do?

  • incsearch (incremental search): As you type /hel, Vim immediately jumps to the first match for "hel" — you don't have to press Enter first. This lets you see results live as you type.
  • hlsearch (highlight search): Every match in the file gets highlighted in yellow (or your theme's highlight color). Very helpful for seeing how many matches exist.
  • ignorecase: Searching for /hello will match "hello", "Hello", "HELLO", etc.
  • smartcase: If you search for /hello (all lowercase), it matches everything. But if you search for /Hello (with a capital), it only matches "Hello" exactly. This gives you the best of both worlds.

Turn off those yellow highlights: After a search, those highlights can be distracting. Type :noh (short for :nohlsearch) and press Enter to clear them. The highlights come back the next time you search. Many people add a keyboard shortcut for this in their vimrc:

nnoremap <leader>h :nohlsearch<CR>

This lets you press \h to quickly clear search highlights.

Search and Replace (The Substitute Command)

The substitute command is Vim's equivalent of "Find and Replace." It uses this format:

:s/old/new/

Let's break that down:

  • : — enters Command-line mode
  • s — the substitute command
  • /old/ — the text you want to find (the "search pattern")
  • /new/ — the text you want to replace it with

Replace One Occurrence on the Current Line

:s/hello/world/

This finds the first occurrence of "hello" on the current line and replaces it with "world." It only changes one match on one line.

Replace ALL Occurrences on the Current Line

Add the g flag (which stands for global — meaning "all matches"):

:s/hello/world/g

Now it replaces every "hello" on the current line, not just the first one.

Replace in the Entire File

Add % before the s to apply the command to every line in the file:

:%s/hello/world/g

This is the most common form. It means: "On every line (%) in the file, substitute (s) every occurrence (g) of hello with world."

Ask for Confirmation Before Each Replace

Add the c flag to get a confirmation prompt for each match:

:%s/hello/world/gc

For each match, Vim will ask: replace with world (y/n/a/q/l/^E/^Y)?

OptionWhat It Does
yYes — replace this one
nNo — skip this one
aAll — replace this one and all remaining matches
qQuit — stop replacing
lLast — replace this one, then stop

The c flag is very useful when you're not sure if every match should be replaced. For example, if you're renaming a variable from count to total, you might not want to change the word "count" inside a comment or string literal. The confirmation prompt lets you decide case by case.

Case-Insensitive Replace

Add the i flag or use \c in yor pattern:

:%s/hello/world/gi      " The 'i' flag makes it case-insensitive
:%s/\chello/world/g     " \c in the pattern does the same thing

Both of these will match "hello", "Hello", "HELLO", etc.

Substitute Command Cheat Sheet

Here's a summary of all the forms:

CommandWhat It Does
:s/old/new/Replace first "old" on current line
:s/old/new/gReplace ALL "old" on current line
:%s/old/new/gReplace ALL "old" in the entire file
:%s/old/new/gcReplace all, but ask for confirmation each time
:%s/old/new/giReplace all, case-insensitive
:5,10s/old/new/gReplace all on lines 5 through 10
:'<,'>s/old/new/gReplace all in the visually selected text

That last one is super handy! If you select some text in Visual mode (V for line selection) and then type :s/old/new/g, Vim automatically fills in '<,'> (which means "the selected range"). So you can easily do find-and-replace on just a portion of your file.

Replacing on Specific Lines

You can specify exactly which lines to search:

:5,10s/old/new/g       " Only on lines 5 through 10
:.,+5s/old/new/g       " From the current line (.) to 5 lines below
:.,$ s/old/new/g       " From the current line to the end of the file

What do the symbols mean?

  • . means "the current line" (where your cursor is)
  • $ means "the last line in the file"
  • +5 means "5 lines after"
  • 5,10 means "lines 5 through 10"

Special Characters in Replacements

Some characters have special meaning in the replacement part of the substitute command:

CharacterWhat It Does
&Inserts the entire matched text
\1, \2Inserts the first/second captured group (see patterns below)
\nInserts a newline (line break)
\tInserts a tab character
\uMakes the next character uppercase
\lMakes the next character lowercase
\UMakes all following characters uppercase (until \E)
\LMakes all following characters lowercase (until \E)

Example — changing case:

:%s/hello/\U&/g        " Replace "hello" with "HELLO" (\U makes it uppercase, & is the match)
:%s/HELLO/\L&/g        " Replace "HELLO" with "hello" (\L makes it lowercase)

Simple Patterns (Regular Expressions)

Sometimes you need to search for a pattern rather than exact text. For example, "find any number" or "find any word that starts with get."

Vim supports regular expressions (often called "regex") — a way to describe text patterns. Here are the most useful basics:

PatternWhat It MatchesExample
.Any single characterh.t matches "hat", "hot", "hit"
*Zero or more of the previous characterab*c matches "ac", "abc", "abbc"
\+One or more of the previous characterab\+c matches "abc", "abbc" (not "ac")
\?Zero or one of the previous charactercolou\?r matches "color" and "colour"
^Beginning of a line^# matches lines starting with #
$End of a line;$ matches lines ending with ;
\<Start of a word\<get matches "getUser" but not "forget"
\>End of a wording\> matches "running" but not "ingo"
[abc]Any one of these characters[aeiou] matches any vowel
[0-9]Any digit[0-9]\+ matches one or more digits
\dAny digit (shortcut for [0-9])\d\+ matches numbers like "42", "100"
\wA word character (letter, digit, underscore)\w\+ matches words
\sA whitespace character (space, tab)\s\+ matches one or more spaces

Vim's regex is slightly different from other tools! In most programming languages, + means "one or more." In Vim, you need to escape it: \+. Similarly, ? needs to be \?. The characters ., *, ^, $, and [ work without escaping in Vim, but many other special characters need a backslash. If your pattern isn't working, try adding or removing \ before the special character.

Practical Search Pattern Examples

/\d\+                   " Find any number (one or more digits)
/\<function\>           " Find the exact word "function" (not "dysfunction")
/^import                " Find lines that start with "import"
/;$                     " Find lines that end with a semicolon
/TODO\|FIXME\|HACK      " Find any of these words (\| means "or")

Practical Replace Pattern Examples

" Remove trailing whitespace from every line
:%s/\s\+$//g
 
" Add a semicolon to lines that don't already end with one
:%s/[^;]$/&;/g
 
" Convert snake_case to camelCase (basic version)
:%s/_\(\w\)/\u\1/g

Let's break down that last one:

  • _\(\w\) — finds an underscore followed by a word character and captures that character in \(\).
  • \u\1 — replaces with that captured character, but in uppercase (\u).
  • So my_variable becomes myVariable.

The Global Command

The :global command (:g) lets you run a command on every line that matches a pattern. It's extremely powerful:

:g/pattern/command

This means: "Find every line matching pattern, and run command on each of those lines."

Common Uses

:g/TODO/p               " Print all lines containing "TODO"
:g/^$/d                 " Delete all blank lines (^$ matches empty lines)
:g/console.log/d        " Delete all lines with "console.log"
:g/^#/d                 " Delete all comment lines (starting with #)
:g!/pattern/d           " Delete all lines that do NOT match the pattern

:g! (with exclamation mark) inverts the pattern. :g!/important/d means "delete every line that does NOT contain 'important'." You can also write it as :v/important/d — the v command is the same as g!.

Moving Matching Lines

You can also move or copy matching lines:

:g/TODO/m$              " Move all TODO lines to the end of the file
:g/TODO/t0              " Copy (t = transcript) all TODO lines to the top
:g/function/yank A      " Yank all lines with "function" into register a

Searching Across Multiple Files

To search for text across multiple files, you can use Vim's :vimgrep command:

:vimgrep /pattern/ **/*.js      " Search all .js files recursively
:copen                           " Open the results list

This opens a "quickfix list" — a window showing all matches. You can:

  • Press Enter on a line to jump to that match
  • Type :cnext (or :cn) to go to the next match
  • Type :cprev (or :cp) to go to the previous match

For quick project-wide search, most developers use a terminal command like grep or ripgrep (rg) before opening specific files in Vim. But :vimgrep is handy for searching within Vim itself.

Summary

Here's what you've learned:

  • Search forward with /pattern, backward with ?pattern
  • Navigate matches with n (next) and N (previous)
  • * searches for the word under the cursor
  • Substitute (find & replace): :%s/old/new/g for the whole file
  • Add c flag for confirmation: :%s/old/new/gc
  • Range substitution: :5,10s/old/new/g for specific lines
  • Special characters: . (any char), * (zero or more), ^ (line start), $ (line end)
  • Word boundaries: \<word\> matches whole words only
  • Global command: :g/pattern/command runs a command on all matching lines
  • :g/^$/d deletes blank lines, :g/pattern/d deletes matching lines
  • Set incsearch, hlsearch, ignorecase, smartcase in your vimrc for better searching
🏋️

Practice: Search and Replace

Create a practice file and try these exercises:

vim search-practice.txt

Press i to enter Insert mode, type the following text, then press Escape:

Hello World
hello world
HELLO WORLD
The function getData gets data from the server.
The function getUser gets user info.
TODO: fix this bug
TODO: add error handling
This line has   extra   spaces   in it.
var count = 0;
var name = "John";
var age = 25;

Now try these tasks:

  1. Search for "hello" with /hello — how many matches does it find? (Depends on your ignorecase setting!)
  2. Search for "function" with /function, then press n and N to cycle through matches
  3. Replace all "TODO" with "DONE" in the entire file: :%s/TODO/DONE/g
  4. Replace "var" with "let" only on lines 9-11: :9,11s/var/let/g
  5. Delete all blank lines: :g/^$/d
  6. Remove extra spaces (replace multiple spaces with one): :%s/ \+/ /g
  7. Find lines starting with "The": /^The
  8. Delete all lines containing "TODO" (or "DONE" if you already replaced them): :g/DONE/d
Show Solution
" 1. Search for "hello"
/hello
" With ignorecase: matches on lines 1 (Hello), 2 (hello), and 3 (HELLO) = 3 matches
" Without ignorecase: matches only line 2 (hello) = 1 match
" Press n to go to next match, N for previous
 
" 2. Search and cycle through matches
/function
" Cursor jumps to first "function" on line 4
n         " Jumps to "function" on line 5
N         " Jumps back to line 4
 
" 3. Replace TODO with DONE globally
:%s/TODO/DONE/g
" Both TODO lines now say DONE
 
" 4. Replace var with let on specific lines
:9,11s/var/let/g
" Lines 9-11 now start with "let" instead of "var"
 
" 5. Delete blank lines
:g/^$/d
" All empty/blank lines are removed
 
" 6. Remove extra spaces
:%s/ \+/ /g
" "extra   spaces" becomes "extra spaces"
 
" 7. Find lines starting with "The"
/^The
" Cursor jumps to the first line starting with "The"
n        " Jumps to the next such line
 
" 8. Delete lines containing DONE
:g/DONE/d
" The two "DONE:" lines are gone
 
:q!      " Quit without saving when done
Was this page helpful?
SR

Written by the ShellRAG Team

The ShellRAG editorial team writes practical, beginner-friendly Vim tutorials with tested code examples and real-world use cases. Every article is technically reviewed for accuracy and updated regularly.

Learn more about us →