grep1-4 Exercise 1: ERROR with One Line Before and Two After ============================================================= (Run from an empty folder. The first block makes the two practice files from the chapter; your own files can skip it.) cat > app.log <<'EOF' 09:00:01 INFO service starting 09:00:02 INFO loading config 09:00:03 WARN config key 'timeout' missing, using default 09:00:04 INFO connecting to database 09:00:09 ERROR database connection refused 09:00:10 INFO retrying in 5s 09:00:15 ERROR database connection refused 09:00:16 ERROR giving up after 2 attempts 09:00:17 INFO switching to read-only mode 09:00:20 INFO listening on port 8080 09:05:00 INFO health check ok 09:10:00 WARN slow response: 2300 ms 09:10:30 INFO health check ok 09:15:00 ERROR disk usage 95%, ERROR threshold 90% 09:15:01 INFO alert sent 09:20:00 INFO health check ok EOF cat > access.log <<'EOF' 10.0.0.5 GET /index.html 200 10.0.0.7 GET /about.html 200 10.0.0.5 POST /login 302 10.0.0.9 GET /missing 404 10.0.0.5 GET /index.html 200 10.0.0.7 GET /index.html 200 10.0.0.5 GET /dashboard 200 10.0.0.9 GET /missing 404 10.0.0.7 GET /logout 302 EOF # --- the exercise --- grep -n -B1 -A2 --group-separator='-----' ERROR app.log Output: 4-09:00:04 INFO connecting to database 5:09:00:09 ERROR database connection refused 6-09:00:10 INFO retrying in 5s 7:09:00:15 ERROR database connection refused 8:09:00:16 ERROR giving up after 2 attempts 9-09:00:17 INFO switching to read-only mode 10-09:00:20 INFO listening on port 8080 ----- 13-09:10:30 INFO health check ok 14:09:15:00 ERROR disk usage 95%, ERROR threshold 90% 15-09:15:01 INFO alert sent 16-09:20:00 INFO health check ok WHY THIS WORKS AS AN ANSWER --------------------------- -B1 and -A2 add the context, -n numbers the lines, --group-separator replaces the default -- line. A colon after the number marks a matching line (5, 7, 8 and 14); a dash marks a context line. The ERROR on line 5 pulls in line 4 before it and lines 6 and 7 after; but line 7 is itself a match, and so is 8, so their own context overlaps and everything from line 4 to line 10 becomes ONE group. The ERROR on line 14 is far enough away to start a second group (13 to 16). That is why there are two groups rather than four: one group per run of overlapping context, not one per match. Line 14 is printed once although it holds ERROR twice, because grep works in lines.