# ripgrep

ripgrep is a line-oriented search tool that recursively searches your current directory for a regex pattern while respecting your .gitignore rules. It's a replacement of searching tools like The Silver Searcher (opens new window), ack (opens new window), grep (opens new window).

# Basic Usage

Search by a literal term. Command: rg <term> <file>. For example, rg ripgrep ./utilities/ripgrep.md.

Search by a regex expression. Command rg '<regex>' <file>. For example, rg '\w+grep' utilities/ripgrep.md.

Search by a regex expression with escaped characters. For example, rg 'def iterate\(.*\):'.

Search recursively from an entire directory of files. Command rg '<regex>'. For example, rg '\w+grep'.

Ignore hidden files, or binary files, or symlink files, or files defined in .gitignore by default, though you can turn it on by adding more u options: -u/-uu/-uuu/-uuuu.

Filter when term appearing in certain files. Command rg <term> -g '*.<prefix>'. For example, rg ripgrep -g '*.md' only matches ripgrep in a markdown document.

Filter when the term is not appearing in certain files. Command rg <term> -g '!*.<prefix>'. For example, rg ripgrep -g '!*.md' matches ripgrep in any document except markdown.

Filter by file type. Command rg <term> -t<type>. For example, rg ripgrep -tmd.

Replace term1 to term2 in output. Command rg <term1> -r/--replace <term2>. For example, rg ripgrep --replace rg.

Replace by regex grouping in output. Command rg '<re1>' -r/--replace '<re2>'. For example, rg 'title: (?P<title>ripgrep)' --replace 'Title: $title'.

# Advanced Usage

Q: How to search -foo?
A: You can use the -e/--regexp flag like rg -e -foo. Or, you can use rg -- -foo as the special '--' delimiter indicates that no more flags will be provided.

Q: How to show N lines after or before matching lines?
A: You can use -A / -B. For example, rg term -A 1 -B 1 outputs 1 line (A)fter and 1 line (B)efore the matched line.

Q: How to search in ZIP?
A: You can use -z/--search-zip.

# Read the source code

The source code of Ripgrep program reveals it runs below steps for each searching command execution:

Simplified Rust code:

let args = Args::parse();
let mut searcher = args.search_worker(args.stdout())?;
for result in args.walker()? {
    let subject = subject_builder.build_from_result(result);

ripgrep simplifies the construction of arguments and parameters by the builder design pattern.

# Discussions

There are two major grepping utility-families: grep and ack. The former is for the plain searching, and the latter does smart searching, meaning it knows what files should be filtered out. ripgrep is a hybrid solution.

Scanning all files in current working directory seems easy but a challenge to be fast. It involves using a set of tricks to do system call as less as possible. ripgrep uses a Rust library walkdir (opens new window) for the best performance.

Distributing work to a set of workers makes grepping faster, though mutex synchronization makes it slower. ripgrep avoids the mutex lock by using a lock-free solution - Chase-Lev work-stealing queue (opens new window).

Searching via regex can be slow sometimes, for example, '(a*)*c' takes a long time to terminate if using a backtracing engine. ripgrep uses Rust default regex engine, which uses finite automata instead of backtracking.

ripgrep loads a large chunk of data from a file, instead of line by line, which reduces the I/O overhead.

# References

skim + ripgrep + bat makes for an amazing combination for fuzzy search opening files with preview. Added "skvi" for fuzzy search open vim and "rgvi" for combining ripgrep search + vim opening. Aliases are here: https://t.co/2gJLJKm1OY (opens new window) - @mitsuhiko (opens new window)