The Problem#
You have a variable called userData used 30 times in a file and you need to rename it to customerData. You could manually find-and-replace each one, but some occurrences might be inside strings or comments where you don’t want to change them. Vim gives you several approaches depending on how much control you need.
Method 1: Substitution (:%s)#
The fastest approach when you want to rename every occurrence unconditionally.
Replace all occurrences#
:%s/userData/customerData/g| Part | Meaning |
|---|---|
% | Entire file |
s | Substitute |
userData | Find this |
customerData | Replace with this |
g | All occurrences per line (not just the first) |
Replace with confirmation#
:%s/userData/customerData/gcThe c flag asks you at each match:
| Key | Action |
|---|---|
y | Yes, replace this one |
n | No, skip it |
a | Replace all remaining |
q | Quit substitution |
l | Replace this one and quit |
This is ideal when the variable name might appear in contexts you don’t want to change (comments, strings, similar names).
Whole-word matching#
Avoid renaming userData inside userDataList or oldUserData:
:%s/\<userData\>/customerData/gc\< and \> match word boundaries — only the exact word userData matches, not substrings.
Case-sensitive replacement#
Vim’s substitution respects your ignorecase setting. Force exact case:
:%s/\CuserData/customerData/gReplace in a specific range#
" Lines 10 through 50 only
:10,50s/userData/customerData/g
" From current line to end of file
:.,$s/userData/customerData/g
" Inside a visual selection
'<,'>s/userData/customerData/gMethod 2: Star Search + cgn#
The most flexible approach — you review and decide at each occurrence with minimal keystrokes.
The workflow#
" 1. Place cursor on the variable name and press * to search for it
*
" 2. Press cgn to change the next match
cgn
" 3. Type the new name
customerData
" 4. Press Esc
Esc
" 5. Press n to find the next occurrence (or N for previous)
n
" 6. Press . to repeat the rename — or n to skip
.Why this works#
*searches for the exact word under the cursor (whole word match)gnis a motion that selects the next search matchcgn= change the next match (deletes it and enters insert mode).repeats the last change — which was “change next match to customerData”nmoves to the next match without changing it (lets you skip)
The power of this approach#
You get full control at every occurrence:
.to renamento skip- No regex to remember
- Works immediately without typing a substitution command
Method 3: Visual Block Rename#
When the variable appears in a predictable column position (like a struct or repeated assignments):
struct Config {
int userData_count;
char *userData_name;
float userData_score;
bool userData_active;
};" 1. Move cursor to the 'u' in the first 'userData'
" 2. Press Ctrl-v to enter visual block mode
" 3. Select down to cover all occurrences: 3j
" 4. Select the width of 'userData': e (or 7l)
" 5. Press c to change the block
" 6. Type: customerData
" 7. Press Esc — all lines updateThis only works when occurrences are aligned vertically.
Method 4: Macro#
When the rename requires context-aware edits that aren’t easily captured by substitution.
" 1. Search for the variable
/userData
" 2. Start recording a macro into register q
qq
" 3. Change the word
ciwcustomerData
" 4. Press Esc
Esc
" 5. Jump to the next occurrence
n
" 6. Stop recording
q
" 7. Replay with @q, or run many times with a count
20@qThe macro stops when n can’t find another match (end of file).
Selective macro#
If you want to skip some occurrences:
" Record a macro that changes and advances
qq ciwcustomerData Esc n q
" At each match, decide:
@q " rename and advance
n " skip and advanceMethod 5: Across Multiple Files#
When the variable exists in many files, combine approaches:
Using argdo + substitution#
" Open all files
:args src/**/*.js
" Replace in all of them
:argdo %s/\<userData\>/customerData/gc | updateThe | update saves each file after substitution.
Using grep + quickfix#
" Find all occurrences across the project
:grep "userData" **/*.js
:copen
" Review each match, rename where needed
:cnext
ciwcustomerData Esc
:cnext
.Using cfdo (quickfix + substitution)#
" Populate quickfix with matches
:grep "userData" **/*.js
" Run substitution on every file in the quickfix list
:cfdo %s/\<userData\>/customerData/gc | updateComparing Methods#
| Method | Best when |
|---|---|
:%s///g | Rename all, no exceptions |
:%s///gc | Rename most, skip a few |
* + cgn + . | Selective, interactive, no regex |
| Visual block | Aligned columns |
| Macro | Complex contextual changes |
argdo/cfdo | Multiple files |
Practical Examples#
Rename a function and its calls#
" Whole-word replace across the file
:%s/\<processOrder\>/handleOrder/gRename a struct field in C#
" Be careful — field names may be substrings of other names
:%s/\<node->data\>/node->value/gcRename a CSS class#
" Across HTML and CSS files
:args **/*.html **/*.css
:argdo %s/\<btn-primary\>/btn-main/gc | updateRename a Python variable with underscore convention change#
" snake_case to camelCase for one variable
:%s/\<user_data\>/userData/gRename in a specific function only#
" Select the function body with vi{ first
vi{
" Then substitute within selection
:s/\<temp\>/result/gNote: after visual select, the command line shows :'<,'> automatically.
Tips for Safe Renaming#
Preview matches first#
Before any substitution, search for the term and review what will match:
/\<userData\>Press n to cycle through matches and see if anything unexpected lights up.
Count occurrences#
:%s/\<userData\>//gn
" Reports: "12 matches on 8 lines" without changing anythingThe n flag counts without substituting.
Undo if something goes wrong#
u " Undo the entire substitution (one step)
:earlier 1m " Go back 1 minute in timeVim’s undo treats the entire :%s as one change, so a single u reverts all replacements.
Best Practices#
- Always use word boundaries (
\<and\>) to avoid renaming substrings - Use
gc(confirm) when you’re not 100% sure every match should change - Use
*+cgn+.for interactive renames where you want full control without typing a regex - Count first with
:%s/old//gnto know how many matches exist before committing - For multi-file renames, save with
| updatein argdo/cfdo so changes persist - If a rename goes wrong,
uundoes the entire substitution in one step - Use
:grep+ quickfix when you need to review occurrences across files before deciding what to change


