← Back to Bash Course | Chapter 10: Text Processing Tools | Lesson 2 of 12

grep Basics

grep searches through text and prints only the lines that match a pattern you give it.

Basic Pattern Matching

grep pattern file prints every line in file that contains pattern. Without any file argument, grep reads from stdin, making it a natural fit for pipelines.

Example: Basic Pattern Matching

bash
#!/bin/bash
printf "apple\nbanana\ncherry\napricot\n" > fruits.txt
grep "ap" fruits.txt
rm -f fruits.txt

Case-Insensitive and Inverted Matches

-i makes the match case-insensitive. -v flips the logic entirely and prints only lines that do NOT match the pattern.

Example: Case-Insensitive and Inverted Matches

bash
#!/bin/bash
printf "Apple\nbanana\nAPRICOT\n" > fruits.txt
echo "case-insensitive:"
grep -i "apple" fruits.txt
echo "inverted:"
grep -v "banana" fruits.txt
rm -f fruits.txt

Counting and Recursive Search

-c prints a count of matching lines instead of the lines themselves. -r (or -R) searches every file in a directory tree recursively, which is handy for finding usages across a codebase.

Example: Counting and Recursive Search

bash
#!/bin/bash
mkdir -p code_demo
echo "TODO: fix this" > code_demo/a.txt
echo "nothing here" > code_demo/b.txt
echo "another TODO" > code_demo/c.txt
grep -c "TODO" code_demo/a.txt
grep -r "TODO" code_demo
rm -rf code_demo

Using grep's Exit Status

grep exits 0 if it found at least one match and 1 if it found none, which lets scripts branch on whether a pattern exists without caring about the matched text itself.

Note: Use -q when you only care about the exit status, since it suppresses the normal output entirely.

Example: Using grep's Exit Status

bash
#!/bin/bash
echo "hello world" > greeting.txt
if grep -q "hello" greeting.txt; then
    echo "pattern found"
fi
if ! grep -q "goodbye" greeting.txt; then
    echo "pattern not found, as expected"
fi
rm -f greeting.txt
Common Mistakes
  1. Forgetting grep is case-sensitive by default; -i is needed for case-insensitive matching.
  2. Using grep pattern * and being surprised by filenames prefixed on every line; that happens automatically whenever more than one file is searched.
  3. Not realizing grep's exit status (0 = found, 1 = not found, 2 = error) is itself useful for scripting, not just its printed output.
Chapter Summary
  • grep -i ignores case; -v inverts the match (prints non-matching lines); -c counts matching lines instead of printing them.
  • grep -r searches recursively through a directory tree.
  • grep's exit status is 0 if at least one match was found, 1 if none were found, and 2 on an error.
  • grep -n prefixes each match with its line number, useful for locating matches in a larger file.
🔒

Chapter Quiz — Complete all 12 topics to unlock

0/12 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.