Grep, Awk, and Sed: Text Processing Power Tools for Production Logs
Master grep, awk, and sed for production log analysis.
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Basic Linux command line
- ✓Familiarity with regular expressions
- ✓Understanding of standard streams (stdin, stdout, stderr)
Use grep to find lines matching a pattern, awk to extract and reformat columns, and sed to substitute text. Chain them with pipes: grep 'ERROR' app.log | awk '{print $1, $5}' | sed 's/ERROR/CRITICAL/g'.
Imagine you're a detective with a stack of papers. Grep is a highlighter that marks every line containing a suspect's name. Awk is a pair of scissors that cuts out specific columns from a table. Sed is a white-out pen that corrects typos across the whole stack. Together, you can highlight, cut, and correct without ever touching a paper.
You're tailing a 2GB production log at 3 AM. The payment service is throwing 500s. You need to find every occurrence of 'TransactionTimeout' in the last hour, extract the order IDs and timestamps, and replace the error code with a more descriptive message. You have 30 seconds before the on-call phone rings again. This is where grep, awk, and sed save your night.
These three tools are the Unix text processing trinity. They're not just for sysadmins—every developer who touches a server needs them. Without them, you're grepping in an IDE that can't handle 2GB files, or writing a Python script that takes 10 minutes to import pandas. With them, you solve the problem in one line.
By the end of this article, you'll be able to build complex text pipelines from memory. You'll know when to use each tool, how to combine them, and—more importantly—when not to. You'll stop fearing raw logs and start treating them like a structured database you query with pipes.
Grep: The Laser-Focused Searcher
Grep is your first line of defense. It finds lines matching a pattern. But most people only use grep 'pattern' file. That's like using a chainsaw to cut butter. Let's talk about the flags that matter.
-i for case-insensitive search. -v to invert match—show everything that doesn't match. -c to count matches. -n to show line numbers. -r for recursive search through directories. -l to list only filenames with matches.
In production, you'll often combine these. Need to find all lines that don't contain 'INFO' in a directory of logs? grep -rv 'INFO' /var/log/. Want to count how many times each error appears? grep -o 'ERROR.*' app.log | sort | uniq -c.
But here's the trap: grep reads the entire file. For a 10GB log, that's slow. Always pipe from tail or head first if you only need recent lines. tail -n 10000 app.log | grep 'CRITICAL' is your friend.
grep 'ERROR' huge.log on a 10GB file can take minutes and spike CPU to 100%. Always limit input with tail or head first. Or use grep --line-buffered when piping to another command to avoid waiting for full output.Awk: The Column Whisperer
Grep finds lines. Awk processes them. It's a full programming language disguised as a command. At its core, awk splits each line into fields ($1, $2, etc.) and lets you print, filter, or compute.
Default field separator is whitespace. Use -F to change it. awk '{print $1, $3}' prints the first and third columns. awk '$2 > 100' prints lines where the second field is greater than 100. awk 'NR==10' prints line 10.
In production, awk shines for log analysis. Log lines often have timestamps, levels, and messages. awk '{print $1, $2, $5}' extracts date, time, and error code. awk -F'[][]' '{print $2}' splits on brackets—useful for Apache logs.
But awk has a learning curve. Start with simple field extraction. Add conditions gradually. And remember: awk processes line by line—it's memory efficient even on huge files.
awk '!seen[$0]++' to remove duplicate lines. Use awk 'NR%2==0' to print even lines. Use awk '{for(i=1;i<=NF;i++) if($i ~ /error/) print NR, $i}' to find which field contains 'error'.Sed: The Stream Editor That Never Forgets
Sed is for editing text in a pipeline. The most common use is substitution: sed 's/old/new/g'. But sed can also delete lines, insert text, and apply multiple edits.
-i edits the file in place (use with caution—backup first). -n suppresses automatic printing, used with p to print only matching lines. d deletes lines. a appends after a line. i inserts before.
In production, sed is perfect for config file changes. Need to update a database connection string across 50 servers? sed -i 's/old_host/new_host/g' /etc/app/config.properties. Need to remove all comment lines? sed -i '/^#/d' config.
But sed's syntax is terse. Use extended regex with -E for readability. And always test without -i first: sed 's/pattern/replacement/' file prints to stdout—verify before committing.
sed -i 's/foo/bar/g' important.conf overwrites the file. If your regex is wrong, you corrupt the config. Always use -i.bak to create a backup: sed -i.bak 's/foo/bar/g' important.conf.Combining Grep, Awk, and Sed: The Pipeline
The real power comes from chaining them. Each tool does one thing well: grep filters lines, awk processes fields, sed edits. Pipe them together to build a processing pipeline.
Classic pattern: grep 'ERROR' log | awk '{print $1, $5}' | sed 's/ERROR/CRITICAL/g'. This finds errors, extracts timestamp and error code, then renames the level.
Another pattern: tail -f log | grep --line-buffered 'ERROR' | awk '{print $1}'. Real-time monitoring of error timestamps.
But beware: each pipe creates a subprocess. For huge files, this can be slow. If you need complex logic, consider a small Python script instead. But for 90% of log analysis, the pipeline is faster to write and run.
grep --line-buffered and awk '{print; fflush()}' to force flush. Without buffering, you might wait minutes for output.When Not to Use These Tools
Grep, awk, and sed are not always the answer. For structured data like JSON or XML, they're fragile. A JSON value with spaces breaks awk's field splitting. A nested XML tag confuses sed.
Use jq for JSON. Use xpath or xmlstarlet for XML. Use Python or Perl for complex multi-line patterns.
Also, for files larger than RAM, these tools still work (they stream), but if you need random access or joins, consider a database or Spark.
Finally, if your pipeline has more than 5 pipes, write a script. It'll be more readable and maintainable.
csvkit or awk -F',' if simple. For log files with consistent format, these tools are unbeatable. For anything else, reach for a purpose-built parser.The 4GB Log That Broke My Editor
grep '2025-03-15 14:' app.log | grep 'ThreadPoolExhausted' | awk '{print $1, $2, $6}' to isolate the exact minute and thread count. Found the pool size was 10—bumped to 50. Problem solved in 15 seconds.- When logs are huge, don't grep the whole file—pipe through multiple greps to narrow down.
- And always know your thread pool limits.
-i. 2. Check if file is binary: use grep -a. 3. Check if pattern has special characters: escape them or use -F for fixed strings.-F' ' explicitly. 2. Print all fields with {print $0} to see the line. 3. Check if fields are empty: use $1 != "" condition.-i first. 2. Use -E for extended regex. 3. Check if pattern contains /: use different delimiter like s|old|new|.grep -i 'pattern' filegrep -a 'pattern' file-i for case-insensitive, -F for fixed string| File | Command / Code | Purpose |
|---|---|---|
| grep_production.sh | tail -n 10000 /var/log/payment.log | grep -i 'CRITICAL' > /tmp/critical_errors.t... | Grep |
| awk_production.sh | awk '{print $4, $5, $10}' /var/log/apache/access.log | head -5 | Awk |
| sed_production.sh | sed -i 's/localhost/db-prod-1/g' /etc/app/database.properties | Sed |
| pipeline_production.sh | tail -n 50000 /var/log/nginx/access.log | grep ' "5[0-9][0-9] ' | awk '{print $1... | Combining Grep, Awk, and Sed |
| when_not_to.sh | echo '{"name": "John Doe"}' | jq -r '.name' | When Not to Use These Tools |
Key takeaways
tail or head before grepping huge files to avoid CPU spikes.-i first, and always use -i.bak for backups.Interview Questions on This Topic
How does grep handle binary files? What flag forces text mode?
-a to treat binary as text. This is critical when grepping through mixed log files that contain null bytes.Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Linux. Mark it forged?
3 min read · try the examples if you haven't