IntelliJ IDEA Find and Replace: Complete Guide
IntelliJ IDEA's Find and Replace functionality is one of the most powerful and feature-rich tools in any modern IDE. It goes far beyond simple text matching, offering structural search, regex-powered replacements, multi-file batch operations, and even awareness of your code's semantics. Mastering it will dramatically accelerate your development workflow.
What It Is
Find and Replace in IntelliJ IDEA is a multi-layered system that lets you search for and optionally replace text, patterns, or code structures across a single file, multiple files, or your entire project. It includes:
- Basic Find/Replace — character-level search within the current file
- Find in Path / Replace in Path — search across directories, modules, or the whole project
- Structural Search and Replace (SSR) — search based on code structure rather than raw text
- Regex mode — full regular expression support with backreferences and lookahead/lookbehind
- Highlighting and navigation — instant visual feedback and quick jumping between matches
Why It Matters
In real-world development, you constantly need to rename symbols, update deprecated API calls, refactor patterns, or fix typos across a large codebase. A naive text search with "find all" and manual editing is slow and error-prone. IntelliJ's tooling gives you:
- Speed — replace hundreds of occurrences in seconds with preview and confirmation
- Accuracy — regex and structural searches prevent false positives (e.g., matching a variable name inside a string literal)
- Context awareness — SSR understands Java/Kotlin/other language constructs, not just raw bytes
- Safety — preview diffs before applying changes, undo history, and exclude patterns
Getting Started: The Find Bar
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →The most immediate tool is the inline Find bar. Press Ctrl+F (Windows/Linux) or Cmd+F (macOS) while focused in any editor. A small panel appears at the top-right of the editor area.
Basic Find Operations
Type your search string and IntelliJ highlights all matches in the current file in real time. Navigate between matches with:
Enter/Shift+Enter— move to next / previous matchF3/Shift+F3— same navigation when the Find bar is closed- Click the up/down arrows in the Find bar
The Find bar also shows a match count (e.g., "12 of 45 matches") so you instantly know how many occurrences exist.
Find Options Toggles
Within the Find bar, several toggle icons control search behavior:
- Match Case (
Alt+C) — enables case-sensitive search - Whole Words (
Alt+W) — matches only when the term appears as a whole word boundary - Regex (
Alt+X) — treats the search string as a regular expression - In Selection (
Alt+E) — limits search to currently selected text
Highlighting and Multi-Cursor Integration
When matches are highlighted, you can press Alt+Enter on any match to perform quick actions, or use Ctrl+Shift+Alt+J (Windows/Linux) / Ctrl+Cmd+G (macOS) to select all occurrences and edit them simultaneously with multi-cursor. This is incredibly fast for local refactoring.
// Example: In this file, all occurrences of "userName" are highlighted
// Press Ctrl+Shift+Alt+J to select all, then type "fullName"
// All instances change simultaneously
public class User {
private String userName;
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
}
// After multi-cursor rename: all "userName" → "fullName" in one action
Replace in Current File
Press Ctrl+H (Windows/Linux) or Cmd+H (macOS) — or click the Replace icon in the Find bar — to open the Replace panel. It expands the Find bar to show a Replace field.
Replace Workflow
- Enter the replacement text in the second field
- Click Replace to replace the current match and advance to the next
- Click Replace All to replace all matches at once
- Click Exclude to skip the current match and move on
When you use Replace All, IntelliJ shows a confirmation dialog listing the number of replacements. You can undo (Ctrl+Z) if something goes wrong.
Regex Replacements with Capture Groups
In Regex mode, you can use capture groups and backreferences in the replacement field. The syntax uses $1, $2, etc., to refer to captured groups.
// Problem: Swap the order of HTML attribute key-value pairs
// From: class="highlight" id="main"
// To: id="main" class="highlight"
// Find (Regex mode):
(\w+)="([^"]*)"
// Replace:
$1="$2"
// But to swap two specific attributes:
// Find:
class="([^"]*)"\s+id="([^"]*)"
// Replace:
id="$2" class="$1"
// Result: class="highlight" id="main" → id="main" class="highlight"
Regex Example: Adding Type Annotations
// Scenario: You have many variable declarations without explicit types
// and want to add type annotations (e.g., for a migration)
// Original code:
var name = "Alice";
var age = 30;
var active = true;
// Find (Regex mode):
var\s+(\w+)\s*=\s*(.+?);
// Replace:
$1: String = $2;
// But this would incorrectly type age and active.
// Better: Use structural search or process in stages.
// This illustrates why context-aware tools matter.
Find in Path / Replace in Path (Multi-File Search)
For project-wide operations, use Find in Path (Ctrl+Shift+F / Cmd+Shift+F) and Replace in Path (Ctrl+Shift+H / Cmd+Shift+H). These open a dedicated tool window.
Configuring the Scope
You can define exactly where IntelliJ searches:
- Whole Project — every file in the project
- Module — a specific module (useful in multi-module Maven/Gradle projects)
- Directory — a selected folder in the project tree
- Custom Scope — a predefined scope you've configured in Settings → Appearance & Behavior → Scopes
- Open Files — only files currently open in editor tabs
- Recently Viewed Files — files from your recent navigation history
File Mask and Exclusions
Use the File Mask field to filter by file extension or pattern. Examples:
*.java— only Java files*.{js,ts,jsx,tsx}— JavaScript/TypeScript files!*.test.*— exclude test files (prefix with!)
Additionally, the Pattern field lets you exclude directories like **/node_modules/** or **/build/** from the search.
Preview and Batch Replace
When you run Replace in Path, IntelliJ first shows a preview panel listing every match with file path, line number, and context. You can:
- Uncheck individual matches to skip them
- Use checkboxes to selectively apply replacements
- Click Replace All after reviewing
- Use Filter to narrow down by file or pattern
This preview step is critical for safety in large codebases.
Example: Renaming a Deprecated Method Across a Project
// Task: Replace all calls to deprecated getOldValue() with fetchValue()
// across the entire project, but only in .java files
// 1. Open Replace in Path: Ctrl+Shift+H
// 2. Search: getOldValue
// 3. Replace: fetchValue
// 4. File Mask: *.java
// 5. Scope: Whole Project
// 6. Click "Find" to preview
// 7. Review matches, uncheck any inside comments or string literals
// 8. Click "Replace All"
// Before (across multiple files):
public void process() {
int x = getOldValue("key");
String label = "getOldValue is deprecated"; // string literal - skip this
}
// After (with manual uncheck of the string literal):
public void process() {
int x = fetchValue("key");
String label = "getOldValue is deprecated"; // preserved correctly
}
Structural Search and Replace (SSR)
SSR is IntelliJ's most sophisticated search capability. Instead of matching raw text, it matches code structure — abstract syntax tree patterns. This means it understands language semantics and can distinguish between a method call, a field access, a string literal, etc.
When to Use SSR
Use SSR when:
- You need to match code patterns that vary in formatting (whitespace, line breaks)
- You want to find all implementations of a pattern regardless of variable names
- You need to replace a structural pattern (e.g., convert a for-loop to a stream)
- Regex would produce too many false positives because it can't understand code context
Opening Structural Search
Go to Edit → Find → Search Structurally (or Replace Structurally). There's no default shortcut, but you can assign one in Settings → Keymap under "Structural Search".
Writing a Structural Search Pattern
SSR patterns use a template syntax where $variable$ represents a placeholder that matches any valid expression/identifier of that position. You can add constraints to variables.
// Example: Find all if-statements that check a boolean flag
// and then assign it to false inside the block
// Structural Search template:
if ($condition$) {
$condition$ = false;
}
// Variables:
// $condition$ — any variable (with constraint: same variable in both positions)
// This matches:
if (isReady) {
isReady = false;
}
// Also matches:
if (flag) {
flag = false;
}
// But NOT:
if (isReady) {
isReady = true; // different value
}
// And NOT:
if (isReady) {
someOtherVar = false; // different variable
}
Adding Variable Constraints
In the SSR dialog, each $variable$ appears in a panel where you can set:
- Type — restrict to a specific type (e.g.,
boolean,String) - Text — match exact text
- Regex — match names by pattern
- Count — number of occurrences (e.g., exactly 1, 0–∞)
- Script — Groovy script constraint for complex logic
Structural Replace Example: Migrating a Pattern
// Scenario: Replace verbose null-check patterns with Optional
// Find template:
if ($var$ != null) {
$expr$.method($var$);
} else {
$default$;
}
// Replace template:
Optional.ofNullable($var$).map(v -> $expr$.method(v)).orElse($default$);
// Variables:
// $var$ — any variable
// $expr$ — any expression
// $default$ — any expression
// Constraint: the method call must use $var$ as argument
// Original code:
if (user != null) {
logger.log(user.getName());
} else {
logger.log("Unknown");
}
// After structural replace:
Optional.ofNullable(user)
.map(v -> logger.log(v.getName()))
.orElse(logger.log("Unknown"));
// SSR handles the variable renaming (user → v) automatically
// to avoid shadowing issues.
SSR for Different Languages
SSR works for Java, Kotlin, Groovy, JavaScript, TypeScript, Python, XML, HTML, and more. Each language has its own template syntax reflecting its grammar. Switch the language in the SSR dialog's dropdown.
Advanced Techniques
Find Usages vs. Find in Path
For symbols (classes, methods, fields), prefer Find Usages (Alt+F7 / Cmd+F7 or right-click → Find Usages). This is even smarter than SSR — it uses the IDE's index and resolves references precisely. It distinguishes between reads, writes, imports, and type references. Use Find in Path only for non-symbol text like comments, string literals, or patterns across languages.
Search Everywhere Integration
Press Shift+Shift to open Search Everywhere. Type //replace: followed by your pattern to jump directly to Replace in Path. Similarly, //find: triggers Find in Path. This is a fast keyboard-only workflow.
// From Search Everywhere:
// Type: //replace:deprecatedMethod
// Opens Replace in Path with "deprecatedMethod" pre-filled
// Type: //find: TODO
// Opens Find in Path searching for "TODO" comments project-wide
Regex Lookahead/Lookbehind in IntelliJ
IntelliJ's regex engine supports advanced constructs. These are useful for context-sensitive replacements without SSR.
// Find: all occurrences of "color" that are NOT followed by "="
// (i.e., avoid matching CSS property names)
// Find (Regex mode):
color(?!\s*=)
// Find: all "port" preceded by "localhost:"
// Replace the port number but keep localhost
// Find:
(?<=localhost:)\d+
// Replace:
8080
// Original: localhost:3000 → localhost:8080
// But: server:3000 remains unchanged (no localhost prefix)
// Find: replace "var" keyword only when NOT inside a comment
// (Simplified: comments often start with //)
// Find:
^\s*var\s+(?!.*//)
// This avoids lines like: // var legacyCode = ...
Using Backreferences in Replace
// Task: Swap two method arguments everywhere
// Original:
service.configure(host, port, timeout);
// Desired:
service.configure(port, host, timeout);
// Find (Regex mode, Match Case):
configure\((\w+),\s*(\w+),\s*(\w+)\)
// Replace:
configure($2, $1, $3)
// $1 = host, $2 = port, $3 = timeout
// Result: configure(port, host, timeout)
Multi-Line Regex Matching
By default, . does not match newline characters. To match across lines, enable the Dot All flag by prefixing your regex with (?s) or checking the "Match multiline" option in the Find panel.
// Find: method declarations that span multiple lines and have no body (abstract)
// (?s) makes . match newlines
(?s)abstract\s+\w+\s+\w+\(.*?\)\s*;
// Matches:
abstract void process(String input);
// Also matches:
abstract void process(
String input
);
// Without (?s), the second form would not match because of the line break.
Find and Replace in Version Control and Diffs
IntelliJ extends Find and Replace into VCS tools. In the Commit Diff view, Local Changes panel, or Version Control log, you can press Ctrl+F to search within the displayed content. This is helpful for reviewing what changed or finding when a particular string was introduced.
Searching Commit Messages
In the Git log (Alt+9 → Log tab), press Ctrl+F to search commit messages. Use regex to find commits matching patterns like ticket numbers:
// Find commits referencing JIRA tickets
// Regex mode:
[A-Z]+-\d+
// Matches: PROJ-1234, BUG-567, FEATURE-89
Best Practices
- Always preview multi-file replacements — Never blind-apply Replace All across a project. Use the preview panel to scan for false positives, especially in string literals, comments, and test data.
- Prefer semantic tools for code — Use Rename refactoring (
Shift+F6) for symbols, Find Usages for references, and SSR for structural patterns. Reserve raw text Find/Replace for comments, documentation, and configuration files. - Leverage file masks aggressively — When replacing across a project, set precise file masks (
*.java,*.xml) to avoid touching unrelated files like binaries or generated code. - Use exclude patterns — Add
**/node_modules,**/dist,**/build,**/.gitto your project's default exclusions in Settings → Editor → File Types → Ignored Files and Folders. - Test regex in the Find bar first — Before committing to a Replace All, test your regex in Find mode. Verify the match count and spot-check matches to ensure your pattern is correct.
- Commit before massive replacements — Run a VCS commit before applying project-wide replacements. If something goes wrong, you can revert cleanly.
- Learn SSR for repetitive migrations — Invest time learning Structural Search syntax. It pays off enormously when you need to migrate patterns across a large codebase (e.g., framework upgrades, API changes).
- Customize shortcuts — Map Structural Search and Replace to memorable shortcuts if you use them frequently. The default lack of shortcuts is a barrier to adoption.
- Use multi-cursor for local edits — For in-file renames of 3–20 occurrences,
Ctrl+Shift+Alt+J(select all occurrences) plus multi-cursor editing is faster than opening the Replace dialog. - Watch out for regex greediness — Use
.*?(lazy) instead of.*(greedy) when matching between delimiters. Greedy matches can consume far more than intended across multiple matches.
// Example of regex greediness pitfall:
// Given text:
<tag>first</tag> <tag>second</tag>
// Greedy regex:
<tag>.*</tag>
// Matches the ENTIRE string: <tag>first</tag> <tag>second</tag>
// (.* consumes everything until the LAST </tag>)
// Lazy regex (correct):
<tag>.*?</tag>
// Matches two separate groups: <tag>first</tag> and <tag>second</tag>
// (.*? consumes minimally until the FIRST </tag>)
Keyboard Shortcut Reference
Here's a consolidated reference of the most important shortcuts:
Ctrl+F/Cmd+F— Find in current fileCtrl+H/Cmd+H— Replace in current file (often requires first opening Find, then clicking Replace icon)Ctrl+Shift+F/Cmd+Shift+F— Find in Path (project-wide)Ctrl+Shift+H/Cmd+Shift+H— Replace in PathAlt+F7/Cmd+F7— Find Usages of symbol at cursorShift+F6— Rename refactoring (safe symbol rename)Ctrl+Shift+Alt+J/Ctrl+Cmd+G— Select all occurrences (multi-cursor)F3/Shift+F3— Next / Previous match (when Find bar is closed)Shift+Shift— Search Everywhere (prefix with//find:or//replace:)Alt+C, Alt+W, Alt+X, Alt+E— Toggle Match Case, Whole Words, Regex, In Selection (within Find bar)
Conclusion
IntelliJ IDEA's Find and Replace ecosystem is a deep, multi-layered toolkit that scales from quick in-file edits to sophisticated cross-project structural transformations. By understanding when to use basic text search, regex patterns, multi-cursor selection, or full Structural Search and Replace, you can handle virtually any code modification task with precision and confidence. The key is matching the tool to the task: use multi-cursor for local renames, Find/Replace in Path for text patterns across files, Find Usages for symbol references, and SSR for complex structural migrations. Master these tools, and you'll spend less time on mechanical editing and more time solving real problems.