Skip to content

Practice Examples

Try these exercises to solidify your understanding:

Practice Exercises

Learning by Doing

Try each exercise in order. The expected output is shown to help you verify your results.

graph LR
    Start[Start Here] --> Basic["Exercise 1
    Basic Search"]

    Basic --> FlagsBox["Exercises 2-6
    Search Flags"]

    FlagsBox --> AdvBox["Exercises 7-8
    Advanced Patterns"]

    AdvBox --> FilterBox["Exercises 9-10
    Filtering"]

    FilterBox --> OutputBox["Exercise 11
    Output Format"]

    OutputBox --> Challenge["Exercise 12
    Advanced Challenge"]

    Challenge --> Practice[Practice More]

    style Start fill:#e8f5e9
    style Basic fill:#e1f5ff
    style FlagsBox fill:#fff3e0
    style AdvBox fill:#f3e5f5
    style FilterBox fill:#fce4ec
    style OutputBox fill:#e0f2f1
    style Challenge fill:#ffebee
    style Practice fill:#e8f5e9

Figure: Learning progression showing how exercises build from basic to advanced techniques.

Find all TODO comments in your project:

rg "TODO"

Expected Output

src/main.rs
15:    // TODO: Implement error handling
42:    // TODO: Add validation

Find all error messages (any case):

rg -i "error"

Tip

Learn more about case sensitivity options in Case Sensitivity.

Expected Output

src/lib.rs
23:    return Err("Error: invalid input");
src/utils.rs
8:    log.error("Connection failed");

Find function calls to "log()" (literal match, not regex):

rg -F "log()"

Note

The -F flag treats the pattern as a literal string, so special regex characters like () are matched exactly. Learn more in Literal Search.

Expected Output

src/main.rs
67:    log("Starting process");

4. Word Boundaries

Find variable named "id" (not "valid", "identity", etc.):

rg -w "id"

Tip

Learn more about word boundaries and anchors in Boundaries.

Expected Output

src/models.rs
12:    pub id: u64,
34:    let id = self.get_id();

5. Count Matches

Count how many times each file uses "import":

rg -c "import"

Tip

Learn more about counting and listing matches in Count and List.

Expected Output

src/main.rs:3
src/lib.rs:7
src/utils.rs:2

Note

Files with zero matches are not shown by default.

6. Context Lines

Find errors with surrounding context:

rg -C 3 "error"

Expected Output

src/lib.rs
20-    fn process() -> Result<()> {
21-        if !valid {
22-            return Err("error: validation failed");
23-        }
24-        Ok(())
25-    }

7. Regex Pattern

Find hexadecimal numbers:

rg "0x[0-9a-fA-F]+"  # (1)!
  1. Pattern breakdown: 0x matches literal "0x" prefix, [0-9a-fA-F] matches any hex digit (0-9, a-f, A-F), + matches one or more digits

Tip

Learn more about regex patterns in Pattern Matching and Regex Basics.

Expected Output

src/constants.rs
5:    const MASK: u32 = 0xFF00;
8:    const OFFSET: u64 = 0x1000ABCD;

8. Inverted Match

Find all non-empty lines:

rg -v "^$"

Note

This is useful for filtering out blank lines from output or counting lines of actual content.

9. File Type Filtering

Find imports only in Rust files:

rg -t rust "^use "

Expected Output

src/main.rs
1:use std::fs;
2:use std::io;

Tip

Use rg --type-list to see all available file types. Learn more in File Filtering.

Find struct definitions that span multiple lines:

rg -U "struct \w+\s*\{[^}]+\}" --type rust  # (1)!
  1. Pattern breakdown: -U enables multiline mode, struct \w+ matches "struct" followed by a name, \s*\{ matches optional whitespace and opening brace, [^}]+ matches one or more non-brace characters (the struct body), \} matches closing brace

Expected Output

src/config.rs
10:struct Config {
11:    pub enabled: bool,
12:    pub timeout: Duration,
13:}

Advanced Pattern

The -U flag enables multiline mode. Source: tests/multiline.rs

11. JSON Output

Get structured JSON output for parsing:

rg "TODO" --json

Expected Output

{"type":"match","data":{"path":{"text":"src/main.rs"},"lines":{"text":"    // TODO: Implement\n"},"line_number":15,"absolute_offset":342,"submatches":[{"match":{"text":"TODO"},"start":7,"end":11}]}}

Tip

JSON output is useful for integrating ripgrep into tools and scripts. Learn more in Output Formatting.

12. Advanced Challenge

Combine multiple concepts - search for TODO comments in Rust files only, case-insensitive, with 2 lines of context, output as JSON:

rg -t rust -i "TODO" -C 2 --json

Expected Output

{"type":"context","data":{"path":{"text":"src/main.rs"},"lines":{"text":"fn main() {\n"},"line_number":13,"absolute_offset":280,"submatches":[]}}
{"type":"match","data":{"path":{"text":"src/main.rs"},"lines":{"text":"    // TODO: Implement error handling\n"},"line_number":15,"absolute_offset":342,"submatches":[{"match":{"text":"TODO"},"start":7,"end":11}]}}
{"type":"context","data":{"path":{"text":"src/main.rs"},"lines":{"text":"    process();\n"},"line_number":16,"absolute_offset":378,"submatches":[]}}

Challenge Yourself

Try modifying this command to:

  • Exclude test files: add -g '!*test*'
  • Only show file names: replace --json with -l
  • Count matches per file: replace -C 2 --json with -c

Common Mistakes

flowchart TD
    Start[Need to Search?] --> Special{"Contains
special chars?
. * + ? etc."}

    Special -->|Yes| Literal["Use -F flag
for literal search"]
    Special -->|No| Case{"Case
matters?"}

    Case -->|No| CaseFlag["Use -i flag
case-insensitive"]
    Case -->|Yes| Whole{"Match whole
words only?"}

    Whole -->|Yes| Word["Use -w flag
word boundaries"]
    Whole -->|No| Hidden{"Search
hidden files?"}

    Hidden -->|Yes| HiddenFlag["Use --hidden
--no-ignore"]
    Hidden -->|No| Type{"Specific
file types?"}

    Type -->|Yes| TypeFlag["Use -t flag
file type filter"]
    Type -->|No| Search[Run search]

    Literal --> Search
    CaseFlag --> Search
    Word --> Search
    HiddenFlag --> Search
    TypeFlag --> Search

    style Start fill:#e8f5e9
    style Special fill:#fff3e0
    style Literal fill:#e1f5ff
    style Search fill:#c8e6c9

Figure: Decision flowchart for choosing the right ripgrep flags to avoid common mistakes.

Forgetting to Escape Regex Metacharacters

Problem:

# This searches for regex pattern "file.txt", which matches "file_txt", "fileXtxt", etc.
rg "file.txt"

Solution:

# Use -F for literal search
rg -F "file.txt"

# Or escape the dot
rg "file\.txt"

Case Sensitivity Confusion

Problem:

# Doesn't match "TODO", "Todo"
rg "todo"

Solution:

# Use -i or -S for smart case
rg -i "todo"
rg -S todo

Matching Partial Words

Problem:

# Matches "test", "testing", "contest", "latest", etc.
rg "test"

Solution:

# Use -w for whole words only
rg -w "test"

Hidden Files Not Searched by Default

Problem:

# Doesn't search .env, .gitignore, or files in .git/
rg "SECRET_KEY"

Solution:

# Use --hidden to search hidden files
rg --hidden "SECRET_KEY"

# Use --no-ignore to also search ignored files
rg --hidden --no-ignore "SECRET_KEY"

Note

ripgrep respects .gitignore by default for better performance. Source: crates/ignore/src/lib.rs

Binary Files Skipped Automatically

Problem:

# Searches text files but skips binary files like images, executables
rg "pattern"

Solution:

# Use -a to search binary files (may produce garbled output)
rg -a "pattern"

# Use --binary to search binary files but show only filenames
rg --binary "pattern"

Tip

For searching specific binary formats, consider specialized tools or convert to text first.

Not Using File Type Filters

Problem:

# Searches all files, slower on large codebases
rg "function"

Solution:

# Much faster: only search JavaScript/TypeScript files
rg -t js -t ts "function"

# Exclude test files
rg -t rust "TODO" -g '!*test*'

Performance Boost

File type filters dramatically improve speed on large projects. Source: crates/ignore/src/types.rs