| ripgrep vs grep |
If you write code, wrangle logs, or spelunk through vast text forests, you’ve heard the whispers: ripgrep, a.k.a. rg, is the new monarch of search. It’s fast—sometimes startlingly so. It’s friendly—respecting your project boundaries out of the box. And it’s flexible—jumping between regex engines when you need the heavy artillery. So… is legendary grep finally obsolete?
Not quite. But the landscape has shifted. Here’s the state of play.
The Old King vs. the New Sprinter
grep is the venerable workhorse: ubiquitous, POSIX-flavored, and unquestionably reliable. It’s everywhere your shell is. Meanwhile, ripgrep is the speed-first, developer-centric sprinter built in Rust. It recurses smartly, parallelizes aggressively, and avoids searching junk you didn’t mean to search in the first place.
Rule of thumb: if you’re searching a codebase or a repo with modern tooling, ripgrep feels like turbo mode; if you’re working in minimal environments or tiny pipelines that must run on any Unix box, grep remains the universal lingua franca.
Why ripgrep Often Feels “Instant”
ripgrep defaults to sane, project-aware filters. That means it automatically:
-
Skips files and folders ignored by your VCS rules (like
.gitignore), -
Hides dotfiles unless asked,
-
Avoids binary files,
-
And doesn’t follow symlinks unless you tell it to.
The practical effect? Less I/O churn, fewer irrelevant hits, more signal per keystroke. You can flip all that off with -uuu if you want the “search it all” behavior, but the defaults are tuned for humans moving fast in real codebases.
Regex Power: PCRE2 When You Need It
By default, ripgrep uses a lightning-quick regex engine that guarantees linear-time searching—great for most patterns. When you need backreferences or look-arounds, opt-in to PCRE2 with -P (or --engine pcre2). Need to match across paragraphs or JSON blobs? Enable multiline with -U (--multiline) and go hunting across newlines.
This dual-engine model is deceptively powerful: you live on the fast lane until you need the precise scalpel.
Practical Flags You’ll Actually Use
-
Speed with sense:
rg foo
Starts fast, respects your repo’s ignore rules. -
Case when it matters:
rg -S login
“Smart case”: lowercase pattern = case-insensitive; otherwise, case-sensitive. -
Literal strings:
rg -F "SELECT * FROM users"
Treats pattern as plain text; great for symbols and punctuation-heavy snippets. -
File type targeting:
rg -t ts "debounce"orrg -T vendor pattern
Include only TypeScript, or exclude vendor trees. -
Multiline hunting:
rg -U -P "(?s)BEGIN.*?END"
Opt-in PCRE2 + multiline to span blocks. -
Binary/text control:
rg -a pattern
Force “treat as text” if ripgrep thinks a file is binary.
Where grep Still Wins
-
Everywhere availability. If your script must run on the tiniest container or an ancient appliance,
grepis guaranteed to be there. -
Tiny, single-file tasks. For quick one-liners on a single file, the difference is academic.
-
Strict POSIX/compat pipelines. Some environments require the classic semantics and flags of
grepfor compatibility or policy reasons.
Also worth noting: GNU grep keeps evolving—faster internals, modern PCRE2 hooks, subtle behavior tweaks—so the “grep is stagnant” take is simply outdated.
Performance Reality Check
Benchmark graphs are fun, but your bottleneck is often storage latency, not CPU cycles. On cold disks or remote mounts, both tools wait on I/O. Where ripgrep consistently shines is realistic dev workflows: large trees, lots of files, steady search cadence, and results pruned by ignore rules. That combination makes rg feel instantaneous in day-to-day work.
Migration Tips for the grep-pilled
-
Start with muscle-memory parity:
-
grep -R "foo"→rg "foo"(recursive is default) -
grep -i→rg -i(or try-S) -
grep -F→rg -F
-
-
Embrace types:
rg -t go http.HandleFunc -
Make it your editor’s backend: set
rgas the search engine in Vim/Neovim, Helix, VS Code terminals, etc. -
Keep an escape hatch:
rg -uuuwhen you truly want everything, everywhere, all at once.
Verdict: Is grep Dead?
No. grep is immortal—a standard, a reference point, a last-resort tool on machines where you can’t assume anything else. But for developers in modern repos, ripgrep is the default you should reach for first. It respects your project. It spares your eyes. It flies.
Use grep when you must. Use ripgrep when you can. Your future self will thank you.
FAQ (Lightning Round)
“Why doesn’t rg see my file?”
It’s probably ignored, hidden, or detected as binary. Try rg -uu (fewer filters) or rg -uuu (no filters), or --no-ignore to skip ignore rules.
“My look-around regex doesn’t work.”
Enable PCRE2: rg -P (and -U if it must span multiple lines).
“Can it search compressed files?”
Yes: rg -z will transparently search inside common compressed formats (tools must be installed).
“Is Unicode handled correctly?”
By default, ripgrep’s regexes are Unicode-aware—word boundaries, classes like \d/\w, and case folding all behave sensibly for modern text.
“I only want file names.”
Use -l (list files) or -L (list files without matches).
Quick Cheatsheet
# Fast, project-aware search
rg pattern
# Smart case
rg -S login
# Only in specific languages
rg -t rust Result
# Multiline + PCRE2
rg -U -P "(?s)BEGIN.*?END"
# Show file paths only
rg -l "TODO"
# Disable all filtering (hidden, binary, ignore rules)
rg -uuu pattern
# Treat as literal text
rg -F "user.name(email)"
Happy hunting. rg on. grep on. Text never stood a chance.
Comments
Post a Comment