Theory
Searching the logs
The campus server's log file has thousands of lines, and you need the ones that say ERROR. Scrolling by hand is hopeless. This is the everyday job of grep: give it a pattern and a file, and it prints every line that matches.
grep is one of the most-used commands in all of Linux, and it comes in three flavours, grep, egrep, and fgrep, that differ in how they interpret your pattern. This lesson shows all three and the handful of flags that make grep genuinely powerful.
At a glance
| Command | How it reads the pattern |
|---|---|
| grep | Basic regular expressions (the default) |
| egrep (grep -E) | Extended regular expressions: |, +, ?, ( ) without escaping |
| fgrep (grep -F) | A fixed literal string: no regex, special characters match themselves |
| -i | Flag: case-insensitive matching |
| -c / -n | Flag: count matching lines / show line numbers |
| -v | Flag: invert, show lines that do NOT match |
Practical
grep searching a log (verified)
$ grep "ERROR" log.txt # lines containing ERROR
ERROR disk full
ERROR timeout
$ grep -c "ERROR" log.txt # count them instead
2
$ grep -i "info" log.txt # case-insensitive: INFO and info
INFO started
info lowercase
$ grep -E "ERROR|WARN" log.txt # extended: ERROR or WARN
ERROR disk full
ERROR timeout
WARN low memoryFormula
Pick the variant to match your pattern
Choose by what your pattern needs. Use plain grep for a simple pattern or basic regex. Use egrep (or grep -E) when your pattern uses extended features like | (or), +, or grouping, so you can write them without backslashes. Use fgrep (or grep -F) when you want to match a literal string exactly, treating characters like . and * as themselves, not as regex.
And remember the flags: -i ignores case, -c counts, -n numbers the lines, -v shows what does NOT match. These turn grep from a finder into a precise investigative tool.
Quiz
You want to count how many lines in log.txt contain the word ERROR, case-sensitively. Which command is best?
- grep -v "ERROR" log.txt, which counts matches
- grep -c "ERROR" log.txt, which prints the number of matching lines
- grep -i "ERROR" log.txt, which counts matches
- fgrep counts automatically without a flag
Show the answer
grep -c "ERROR" log.txt, which prints the number of matching lines
grep -c prints the COUNT of matching lines, so grep -c "ERROR" log.txt gives the number directly (here, 2). Option A uses -v, which INVERTS the match, it would show or count the lines WITHOUT ERROR, the opposite of what you want. Option C uses -i (case-insensitive) and, more importantly, does not count, it prints the matching lines themselves; -i would also match 'error' in lowercase, breaking the 'case-sensitive' requirement. Option D is wrong: no grep variant counts without the -c flag. Match the flag to the task: -c to count, -i for case-insensitive, -v to invert, -n for line numbers.
Think first
Why does fgrep exist if grep can already search?
grep handles patterns, so why have fgrep for fixed strings? What does 'fixed' buy you? Then tap.
Show the answer
fgrep (grep -F) treats your pattern as a LITERAL string, which is both SAFER for special characters and FASTER. The safety point: regex characters like . * [ ] ^ $ have special meaning in normal grep, so searching for a real dotted string like an IP address '192.168.1.1' with plain grep would let each . match ANY character, giving false matches. With fgrep, those characters are taken literally, so 'a.b' matches only a real 'a.b', not 'aXb'. That is exactly why you reach for fgrep when your search text contains regex metacharacters you want treated as ordinary text (file paths, IP addresses, code snippets). The speed point: because fgrep does not have to interpret a regular expression, just find a fixed string, it can be faster, which matters when scanning very large files. So fgrep is the right tool when you know your target is an exact literal string: you avoid accidental regex surprises and get a quick, predictable search. If your text has dots, brackets, or asterisks that you mean literally, fgrep saves you from escaping every one of them. Literal and fast: that is fgrep's niche.
Summary
Key takeaways
- grep searches text for a pattern and prints the matching lines, the everyday way to search logs and files.
- grep uses basic regex; egrep (grep -E) uses extended regex (|, +, ?, grouping without escaping).
- fgrep (grep -F) matches a fixed literal string: special characters are taken literally, and it is fast.
- Key flags: -i case-insensitive, -c count matching lines, -n show line numbers, -v invert (non-matching), -r recursive.
- grep -c "ERROR" counts matching lines; grep -i matches regardless of case; grep -v shows what does not match.
- Use fgrep for literal text containing regex characters (paths, IPs) to avoid accidental matches.
- Memory hook: grep basic, egrep extended, fgrep fixed; -i -c -n -v are the everyday flags.