_____                   _             ___     _________  __
 |_   _|__ _ __ _ __ ___ (_)_ __   __ _| \ \   / / ____\ \/ /
   | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | |\ \ / /|  _|  \  /
   | |  __/ |  | | | | | | | | | | (_| | | \ V / | |___ /  \
   |_|\___|_|  |_| |_| |_|_|_| |_|\__,_|_|  \_/  |_____/_/\_\
intermediate11 min

Text Search with grep: Practical Examples

What is grep?

grep (Global Regular Expression Print) is one of the most fundamental and powerful tools for text searching in Unix and Linux systems. It is used to find lines matching a specific pattern within file contents or command outputs. Its name comes from the g/re/p command in the ed editor, which means "globally search for a regular expression and print matching lines."

grep holds an indispensable place in the daily workflow of virtually everyone from system administrators to software developers, data analysts to security specialists. It is used in many different scenarios such as searching for errors in log files, finding a specific function in source code, or filtering large datasets. As one of the most fundamental terminal tools, grep reveals its true power when combined with the pipe mechanism.

Basic Usage

The simplest usage of the grep command is as follows:

# Basic syntax
$ grep "search_text" filename

# Example: search for "error" in a file
$ grep "error" log.txt

# Search in multiple files
$ grep "error" log1.txt log2.txt log3.txt

# Search in all .txt files
$ grep "error" *.txt

The commands above print all lines containing the word "error" in the specified files. The matching portion is shown in color by default. grep is case-sensitive; meaning "error" and "Error" are treated differently.

Common Flags

-i: Case-Insensitive Search

Performs the search without distinguishing between uppercase and lowercase letters. This is especially useful when searching for errors in log files because they may be written as "Error", "ERROR", or "error".

# Search regardless of case
$ grep -i "error" log.txt
# Finds "error", "Error", "ERROR", "eRrOr" — all of them

-r (or -R): Recursive Search in Directories

Searches through all files in the specified directory and its subdirectories. This is extremely useful for finding a specific text in large projects.

# Search recursively in current directory and subdirectories
$ grep -r "TODO" .

# Recursive search in a specific directory
$ grep -r "function" /home/user/project/src/

# Recursive search in specific file types
$ grep -r --include="*.js" "console.log" .

-n: Show Line Numbers

Displays the line number of each matching line within the file. This is ideal for finding the exact location of an error or searched text when working with code.

# Search with line numbers
$ grep -n "main" program.c
# Output: 12:int main(int argc, char *argv[]) {

-v: Invert Match

Shows lines that do NOT match the specified pattern. This is very useful for filtering operations.

# Show lines that don't contain "debug"
$ grep -v "debug" app.log

# Exclude comment lines
$ grep -v "^#" config.conf

# Exclude empty lines
$ grep -v "^$" file.txt

-c: Show Match Count

Returns the number of matching lines. Useful when you only want to know how many lines match rather than viewing the lines themselves.

# How many lines contain "warning"?
$ grep -c "warning" server.log
# Output: 47

-l: Show Only File Names

Lists only the names of files that contain matches, without showing line contents. Ideal for quickly seeing which files contain the relevant text when searching across multiple files.

# Which files contain the word "password"?
$ grep -l "password" *.conf

# List file names recursively
$ grep -rl "deprecated" src/

grep with Regular Expressions (Regex)

The true power of grep emerges when combined with regular expressions. Regular expressions provide a special syntax for defining text patterns.

# Lines starting with "Error" at the beginning
$ grep "^Error" log.txt

# Lines ending with "failed"
$ grep "failed$" log.txt

# Match any single character (.)
$ grep "h.t" file.txt   # matches hat, hot, hit, hut, etc.

# One or more repetitions (+) — use egrep or grep -E
$ grep -E "go+d" file.txt   # god, good, goood, etc.

# Match one of specific characters ([])
$ grep "[aeiou]" file.txt   # Lines containing vowels

# Lines containing digits
$ grep "[0-9]" file.txt

# Search for IP address format
$ grep -E "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" access.log

# Search for email format
$ grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" contacts.txt

grep with Pipes

When used with the pipe (|) operator, grep becomes a perfect tool for filtering the output of other commands. This is one of the finest examples of the Unix philosophy.

# Search running processes
$ ps aux | grep "nginx"

# Filter network connections
$ netstat -an | grep ":80"

# Search command history
$ history | grep "git commit"

# Chain filtering with multiple greps
$ cat access.log | grep "POST" | grep "api" | grep -v "health"

# Find specific directory in disk usage
$ df -h | grep "/home"

# Search environment variables
$ env | grep "PATH"

egrep and fgrep

egrep is the version of grep that supports extended regular expressions and is equivalent to grep -E. fgrep performs fixed-string searches (no regex interpretation) and is equivalent to grep -F.

# Using OR operator with egrep
$ egrep "error|warning|critical" log.txt
# or
$ grep -E "error|warning|critical" log.txt

# Searching special characters literally with fgrep
$ fgrep "price=$10.00" data.txt
# or
$ grep -F "price=$10.00" data.txt

Practical Use Cases

Error Analysis in Log Files

# Find errors in the last 1000 lines
$ tail -1000 /var/log/syslog | grep -i "error"

# Find errors in a specific date range
$ grep "2026-02-14" app.log | grep -i "error"

# Show lines before and after the error (context)
$ grep -B 3 -A 3 "Exception" app.log

# Count unique error messages
$ grep -i "error" app.log | sort | uniq -c | sort -rn

Searching Source Code

# Finding unused functions in a project
$ grep -rn "function oldMethod" src/

# Listing TODO and FIXME comments
$ grep -rn -E "(TODO|FIXME|HACK|XXX)" src/

# Finding files that use a specific import
$ grep -rl "import.*React" src/ --include="*.tsx"

Performance Tips

  • Use -F for fixed-string searches: Disabling the regex engine speeds up the search significantly.
  • Limit file types with --include: Save time by skipping unnecessary files.
  • Skip binary files: The -I flag automatically skips binary files.
  • Use -m for large files: Stops the search after a specified number of matches.
  • Consider ripgrep (rg) as an alternative: It runs much faster than grep on very large codebases.

Summary

grep is the most fundamental and powerful text search tool in the terminal world. It covers a wide range of uses from simple text searches to complex regular expressions, from log analysis to code scanning. Learning flags such as -i, -r, -n, -v, -c, and -l will greatly speed up your daily workflow. When combined with the pipe mechanism, it offers virtually unlimited filtering and searching power. Using grep effectively is one of the most important building blocks of your terminal mastery.