When working with command-line tools, we often need to add contextual information to each line of output. A common scenario is prefixing log lines with "[ERROR]" or timestamps for better readability and processing.
The simplest approach uses sed
(stream editor):
command | sed 's/^/[ERROR] /'
Example with actual commands:
ls -l | sed 's/^/[INFO] /'
When your prefix contains special characters like forward slashes, use a different delimiter:
grep "pattern" file.txt | sed 's|^|[ERROR:404] |'
For more complex scenarios, consider these approaches:
Using awk
command | awk '{print "[DEBUG]", $0}'
Using Perl
command | perl -pe 's/^/[WARN] /'
Using while read loop
command | while read line; do echo "[TRACE] $line"; done
For large files or streams:
sed
is generally fastestawk
offers more flexibility- Shell loops are slowest but most readable
Adding timestamps to application logs:
tail -f /var/log/app.log | sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') /"
Only prefix lines matching a pattern:
command | sed '/error/!s/^/[OK] /; /error/s/^/[ERROR] /'
Common issues and solutions:
# Problem: Prefix disappears for blank lines
command | sed 's/^$.$/[ERROR] \1/'
# Problem: Color codes interfere
command | sed 's/^/\x1b[31m[ERR]\x1b[0m /'
As developers, we frequently need to process log files or command output
where we want to add a prefix to every line. Common use cases include:
- Adding severity tags like [ERROR] or [INFO] to log entries
- Adding timestamps to each line of output
- Marking processed lines with a prefix for debugging
The simplest solution is using sed (stream editor):
command | sed 's/^/[ERROR] /'
Example with actual output:
$ echo -e "line1\nline2" | sed 's/^/[ERROR] /'
[ERROR] line1
[ERROR] line2
For more complex scenarios, awk provides better flexibility:
command | awk '{print "[ERROR] " $0}'
Benefits of using awk:
- Better handling of special characters
- Can conditionally add prefixes
- Allows more complex formatting
Example with conditional prefixing:
$ echo -e "error: crash\nwarning: memory\ndebug: trace" | awk '/error/ {print "[CRITICAL] " $0; next} {print "[LOG] " $0}'
[CRITICAL] error: crash
[LOG] warning: memory
[LOG] debug: trace
For large files (GBs of data), consider these optimizations:
1. Use sed for simplest cases (fastest)
2. For complex transformations, use awk's efficient text processing
3. Avoid piping through multiple commands when possible
Benchmark example:
# Test with 1 million lines
$ time seq 1000000 | sed 's/^/PREFIX/' > /dev/null
real 0m0.347s
$ time seq 1000000 | awk '{print "PREFIX" $0}' > /dev/null
real 0m0.521s
When working with variables in the prefix:
prefix="[$(date +%T)] "
command | awk -v prefix="$prefix" '{print prefix $0}'
Example output:
[14:23:45] Server started
[14:23:45] Listening on port 8080
When your prefix contains special regex characters:
# Escape special chars for sed
prefix="[ERROR\\] "
command | sed "s/^/${prefix//\\/\\\\}/"
Or safer with awk:
prefix="[ERROR] "
command | awk -v p="$prefix" '{print p $0}'