Search and Replace - Finding and Transforming Text with Precision
Learning Objectives: By the end of this lesson, you will be able to:
- Search for text using various patterns and options
- Navigate between search results efficiently
- Perform simple and complex text replacements
- Use regular expressions for powerful pattern matching
- Apply search and replace operations across multiple files
- Understand and use different search modes and flags
- Handle case sensitivity and word boundaries in searches
- Use search for navigation and text selection
1. Welcome and Introduction (5 minutes)
Icebreaker Activity
Imagine you’re an archaeologist who needs to find specific artifacts scattered across a vast dig site, then carefully replace damaged pieces with restored ones. Some artifacts are obvious (like searching for “error” in code), while others require pattern recognition (like finding all email addresses). How would you systematically search and replace with precision and speed?
Lesson Overview
- Duration: 5-6 hours
- Prerequisites: Comfortable with basic Neovim navigation and text editing
- Materials Needed: Text files with various content types (code, data, prose)
2. Learning Objectives and Session Outline (5 minutes)
What We’ll Cover Today:
- Basic Search Operations - Forward and backward text searching
- Search Navigation - Moving between matches efficiently
- Simple Replace Operations - Basic find and replace functionality
- Regular Expression Basics - Pattern matching fundamentals
- Advanced Replace Operations - Complex substitutions with regex
- Multi-file Search and Replace - Operations across multiple files
- Search Options and Modes - Customizing search behavior
- Search-Based Navigation - Using search for efficient movement
Success Criteria:
By the end of this session, you should find any text in any file within seconds, perform complex text transformations using patterns, and handle large-scale refactoring operations across multiple files.
3. Foundation Knowledge (15-20 minutes)
The Philosophy of Search and Replace
Search and replace in Neovim is fundamentally different from traditional editors. It’s not just about finding text—it’s about pattern recognition, precise selection, and powerful transformation.
Real-World Analogy: Think of search and replace like being a detective with a DNA scanner. Basic search is like looking for a suspect by appearance (exact matches), while regex search is like DNA analysis (pattern matching). Replace operations are like systematically updating evidence files with new information.
Why This Matters: Neovim’s search and replace provides:
- Precision: Find exactly what you’re looking for with pattern matching
- Efficiency: Navigate large files faster than scrolling
- Power: Transform text in ways that would take hours manually
- Consistency: Reliable operations that work across all file types
Search and Replace Hierarchy
1. Basic Text Search
- Simple string matching
- Case-sensitive and case-insensitive options
- Forward and backward searching
- Word boundary matching
2. Pattern-Based Search (Regex)
- Pattern matching with wildcards and character classes
- Quantifiers for repetition
- Groups for complex patterns
- Anchors for position-specific matching
3. Replace Operations
- Simple text replacement
- Pattern-based replacement with captured groups
- Conditional replacements
- Multi-line replacements
4. Scope and Range
- Current line replacements
- Selected text replacements
- Entire file operations
- Multi-file operations
Key Terminology
- Pattern: Text or regex used for searching
- Match: Text that fits the search pattern
- Capture Group: Part of regex pattern that can be referenced in replacement
- Substitution: Replace operation with pattern and replacement text
- Flag: Option that modifies search/replace behavior
- Range: Scope of lines where operation applies
4. Detailed Explanation and Examples (25-30 minutes)
Basic Search Operations
Search is one of the most fundamental operations in text editing, providing both text location and navigation functionality.
Forward and Backward Search
/pattern " Search forward for pattern
?pattern " Search backward for pattern
n " Next match (same direction)
N " Previous match (opposite direction)
Search Navigation
* " Search forward for word under cursor
# " Search backward for word under cursor
g* " Search forward for partial word under cursor
g# " Search backward for partial word under cursor
Search Options
/pattern\c " Case insensitive search
/pattern\C " Case sensitive search
/\<pattern\> " Whole word search
/^pattern " Search at beginning of line
/pattern$ " Search at end of line
Basic Replace Operations
The substitute command (:s) is the foundation of text replacement in Neovim.
Basic Substitute Syntax
:s/old/new/ " Replace first occurrence on current line
:s/old/new/g " Replace all occurrences on current line
:%s/old/new/g " Replace all occurrences in entire file
:s/old/new/gc " Replace with confirmation
Range-Based Replacements
:1,10s/old/new/g " Replace in lines 1-10
:.,$s/old/new/g " Replace from current line to end
:'<,'>s/old/new/g " Replace in visual selection
Regular Expression Fundamentals
Regular expressions unlock powerful pattern matching capabilities for complex search and replace operations.
Basic Regex Elements
. " Any character
* " Zero or more of previous
\+ " One or more of previous
\? " Zero or one of previous
\{n,m} " Between n and m of previous
^ " Beginning of line
$ " End of line
\< " Beginning of word
\> " End of word
Character Classes
[abc] " Any of a, b, or c
[a-z] " Any lowercase letter
[0-9] " Any digit
[^abc] " Any character except a, b, or c
\d " Any digit
\s " Any whitespace
\w " Any word character
Capture Groups and Backreferences
\(pattern\) " Capture group
\1, \2, \3 " Reference captured groups in replacement
5. Live Coding Demonstration (20-25 minutes)
Demonstration 1: Basic Search and Navigation
Working with this JavaScript code:
function calculateUserScore(userData) {
const userName = userData.name;
const userAge = userData.age;
const userEmail = userData.email;
if (userName && userAge > 18) {
return processUser(userName, userAge, userEmail);
}
return null;
}
Task: Find and navigate through all occurrences of “user”
-
Start search:
/user -
Navigate through matches:
n " Next occurrence N " Previous occurrence -
Search for whole word only:
/\<user\> " Find "user" as complete word -
Use cursor-based search:
* " Position cursor on "user" and press *
Demonstration 2: Simple Text Replacement
Using the same JavaScript code, let’s rename variables:
Task: Change all “user” prefixes to “customer”
-
Replace on current line:
:s/user/customer/g -
Replace in entire file:
:%s/user/customer/g -
Replace with confirmation:
:%s/user/customer/gc
Demonstration 3: Advanced Regex Replacement
Working with this data file:
John Doe, john.doe@email.com, (555) 123-4567
Jane Smith, jane.smith@email.com, (555) 987-6543
Bob Johnson, bob.johnson@email.com, (555) 456-7890
Task: Format phone numbers consistently
-
Search for phone pattern:
/(\d\{3}) \d\{3}-\d\{4} -
Replace with new format:
:%s/(\(\d\{3}\)) \(\d\{3}\)-\(\d\{4}\)/\1-\2-\3/g -
Result:
John Doe, john.doe@email.com, 555-123-4567 Jane Smith, jane.smith@email.com, 555-987-6543 Bob Johnson, bob.johnson@email.com, 555-456-7890
6. Hands-On Practice (30-40 minutes)
Exercise 1: Basic Search Mastery (10 minutes)
Objective: Master fundamental search operations and navigation
Text Sample:
def process_data(data_list):
processed_data = []
for data_item in data_list:
if validate_data(data_item):
cleaned_data = clean_data(data_item)
processed_data.append(cleaned_data)
return processed_data
def validate_data(data):
return data is not None and len(data) > 0
def clean_data(data):
return data.strip().lower()
Tasks:
-
Find all occurrences of “data”:
- Search forward:
/data - Navigate through all matches using
nandN - Count total occurrences
- Search forward:
-
Search for specific patterns:
- Find “data” at the beginning of words:
/\<data - Find “data” at the end of words:
/data\> - Find whole word “data” only:
/\<data\>
- Find “data” at the beginning of words:
-
Use cursor-based search:
- Position cursor on “process” and use
* - Use
#to search backward - Try
g*for partial matches
- Position cursor on “process” and use
Exercise 2: Simple Replace Operations (15 minutes)
Objective: Practice basic find and replace operations
Starting Code:
<div class="container">
<h1 class="title">Welcome</h1>
<p class="text">This is some sample text content.</p>
<div class="box">
<span class="label">Name:</span>
<input class="input" type="text" />
</div>
<div class="box">
<span class="label">Email:</span>
<input class="input" type="email" />
</div>
</div>
Tasks:
-
Replace class names:
- Change “container” to “wrapper”:
:%s/container/wrapper/g - Change “box” to “field”:
:%s/box/field/g
- Change “container” to “wrapper”:
-
Update attributes:
- Change all “class” to “className”:
:%s/class/className/g
- Change all “class” to “className”:
-
Replace with confirmation:
- Change “text” to “content” with confirmation:
:%s/text/content/gc
- Change “text” to “content” with confirmation:
-
Line-specific replacement:
- On the input lines only, change “input” to “form-control”
- Use visual selection:
Vto select lines, then:'<,'>s/input/form-control/g
Exercise 3: Regular Expression Power (15 minutes)
Objective: Use regex patterns for complex find and replace operations
Data File:
Name,Email,Phone,Date
John Smith,john.smith@company.com,555-123-4567,2023-01-15
Jane Doe,jane.doe@company.com,555-987-6543,2023-02-20
Bob Johnson,bob.johnson@company.com,555-456-7890,2023-03-10
Alice Brown,alice.brown@company.com,555-321-9876,2023-04-05
Tasks:
-
Find email patterns:
- Search for email addresses:
/\w\+@\w\+\.com - Navigate through all email matches
- Search for email addresses:
-
Replace email domains:
- Change all “.com” to “.org”:
:%s/\.com/.org/g
- Change all “.com” to “.org”:
-
Format phone numbers:
- Change from “555-123-4567” to “(555) 123-4567”
- Pattern:
:%s/\(\d\{3}\)-\(\d\{3}\)-\(\d\{4}\)/(\1) \2-\3/g
-
Extract and reorganize names:
- Change “John Smith” to “Smith, John”
- Pattern:
:%s/\(\w\+\) \(\w\+\)/\2, \1/g
-
Date format conversion:
- Change “2023-01-15” to “01/15/2023”
- Pattern:
:%s/\(\d\{4}\)-\(\d\{2}\)-\(\d\{2}\)/\2\/\3\/\1/g
7. Common Pitfalls and Troubleshooting (10 minutes)
Frequent Mistakes
-
Problem: Search doesn’t find obvious matches Cause: Case sensitivity or word boundary issues Solution: Use appropriate flags and options
/pattern\c " Case insensitive /\<pattern\> " Whole word only set ignorecase " Default case insensitive set smartcase " Case sensitive if capitals used -
Problem: Regex pattern doesn’t work as expected Cause: Neovim uses different regex syntax than other tools Solution: Use Neovim-specific syntax or magic mode
/\v(pattern) " Very magic mode (more standard regex) /\V[literal] " Very nomagic mode (literal search) -
Problem: Replace operation affects wrong text Cause: Pattern matches more than intended Solution: Use more specific patterns and test first
:%s/old/new/gc " Use confirmation flag /pattern " Test search pattern first -
Problem: Can’t undo complex replace operation Cause: Large operation without breaking points Solution: Use confirmation or break into smaller operations
:undojoin | s/old/new/g " Join with previous undo
Search Configuration
Enhancing Search Behavior
-- Add to init.lua
vim.opt.hlsearch = true -- Highlight search results
vim.opt.incsearch = true -- Show matches while typing
vim.opt.ignorecase = true -- Ignore case by default
vim.opt.smartcase = true -- Case sensitive if capitals used
vim.opt.wrapscan = true -- Wrap around end of file
-- Clear search highlight
vim.keymap.set("n", "<leader>/", ":nohlsearch<CR>")
Advanced Search Techniques
Multi-line Search
/pattern\_.*pattern " Search across multiple lines
/begin\_.\{-}end " Non-greedy multi-line match
Search History
/<Up> " Previous search
/<Down> " Next search
q/ " Open search history window
8. Best Practices and Professional Tips (5 minutes)
Efficient Search Workflows
Search Strategy
- Start specific: Use exact strings when possible
- Add patterns gradually: Build complex regex step by step
- Test before replacing: Always search first, then replace
- Use confirmation for large operations: Safety with
/gcflag
Navigation Optimization
" Quick search mappings
nnoremap <leader>/ /
nnoremap <leader>? ?
nnoremap <silent> <leader>h :nohlsearch<CR>
Replace Patterns
" Common replace operations
:%s/\s\+$//g " Remove trailing whitespace
:%s/\n\{3,}/\r\r/g " Replace multiple blank lines with two
:%s/\v([a-z])([A-Z])/\1_\L\2/g " camelCase to snake_case
Advanced Search and Replace
Multi-file Operations
:args *.js " Load JS files
:argdo %s/old/new/ge " Replace in all loaded files
:argdo update " Save all files
Complex Transformations
" Convert function declarations
:%s/\vfunction (\w+)\(([^)]*)\)/const \1 = (\2) =>/g
" Format JSON-like data
:%s/\v"(\w+)": "([^"]+)"/"\1": "\2"/g
" Clean up whitespace
:%s/\v\s+/ /g " Multiple spaces to single
:%s/\v^\s+//g " Leading whitespace
:%s/\v\s+$//g " Trailing whitespace
Search-Based Refactoring
Variable Renaming Workflow
- Search for variable:
/oldName - Verify all occurrences with
n - Replace with confirmation:
:%s/oldName/newName/gc - Review changes before saving
Code Pattern Updates
" Update console.log to logger.info
:%s/console\.log(/logger.info(/g
" Convert arrow functions
:%s/\v(\w+) => \{/function(\1) {/g
9. Summary and Review (5 minutes)
Key Takeaways
- Search is navigation: Use search to move around files efficiently
- Pattern power: Regular expressions unlock complex text transformations
- Safety first: Always test patterns before large replace operations
- Scope awareness: Understand what range your operation will affect
- Build incrementally: Start simple and add complexity gradually
Essential Command Categories
" Basic search: /, ?, n, N, *, #
" Simple replace: :s/old/new/g, :%s/old/new/g
" Regex patterns: \d, \w, \s, \+, *, \{n,m}
" Capture groups: \(pattern\), \1, \2
" Flags: g, c, i, I
Quick Review Questions
- How do you search for a whole word only?
- What’s the difference between
nandNin search navigation? - How do you replace all occurrences in the entire file with confirmation?
- How do you reference captured groups in replacement text?
- How do you make a search case insensitive?
Answers:
/\<word\>or use*when cursor is on the wordncontinues in same direction as search,Ngoes opposite direction:%s/old/new/gc- Use
\1,\2, etc. to reference groups defined with\(pattern\) /pattern\cor setignorecaseoption
Building Search and Replace Mastery
Progression Path
- Week 1: Master basic search and simple replacements
- Week 2: Learn regex fundamentals and pattern building
- Week 3: Complex transformations and multi-file operations
- Week 4: Advanced patterns and workflow integration
Daily Practice
- Use search for navigation: Replace scrolling with targeted searching
- Practice patterns: Build regex skills with real-world text
- Refactor regularly: Use search/replace for code improvements
- Explore text: Use search to understand unfamiliar codebases
For Instructors
Teaching Tips
- Start with examples students recognize: Use familiar text types and patterns
- Build regex gradually: Don’t overwhelm with complex patterns initially
- Show mistakes: Demonstrate what happens when patterns go wrong
- Practice recovery: Teach undo and how to fix failed operations
- Use real data: Practice with actual files students work with
Assessment Ideas
- Pattern building tests: Present text transformation requirements
- Speed challenges: Time students finding specific patterns
- Regex translation: Convert requirements to working patterns
- Refactoring exercises: Use search/replace for code modernization
Adaptation Notes
- Different text types: Adapt examples to students’ primary work (data, code, documentation)
- Skill levels: Advanced students can learn lookahead/lookbehind and complex patterns
- Language differences: Some regex features vary by programming language
- Performance considerations: Teach efficient patterns for large files
Common Student Questions
- “Why learn regex when I can do it manually?” - Demonstrate time savings on large operations
- “This seems too complex” - Show how patterns build incrementally
- “What if I break something?” - Emphasize undo system and confirmation flags
- “When would I use this in real work?” - Provide concrete examples from their domain
Remember: Search and replace mastery transforms text editing from tedious character-by-character work to powerful pattern-based operations. This skill multiplies productivity in all text-based work.