← Back to DevBytes

IntelliJ IDEA Find and Replace: Complete Guide

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:

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:

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:

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:

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

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:

File Mask and Exclusions

Use the File Mask field to filter by file extension or pattern. Examples:

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:

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:

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:

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

// 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:

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.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles