Skip to content

/commands/grep/grep-context-lines

grep -A -B -C: show lines before and after each match

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · grep (GNU grep) 3.0updated
tool
grep
versions
GNU grep 3.x
os
linux, macos, windows

grep -A 3 pattern file prints each matching line and the 3 lines after it, -B 3 the 3 lines before it, and -C 3 3 lines on both sides. Add -n to see line numbers: matching lines use : after the number and context lines use -, so you can tell them apart. When two groups of context are not adjacent, grep prints a -- separator line between them.

Example

bash
cat > app.log <<'EOF'
start
loading config
ERROR config missing key
retrying
connected
idle
idle
ERROR timeout
stopping
EOF
grep -n -A 1 ERROR app.log
echo ===
grep -n -B 2 'ERROR timeout' app.log
echo ===
grep -C 1 --no-group-separator ERROR app.log

Output

3:ERROR config missing key
4-retrying
--
8:ERROR timeout
9-stopping
===
6-idle
7-idle
8:ERROR timeout
===
loading config
ERROR config missing key
retrying
idle
ERROR timeout
stopping

In the first command each ERROR line is followed by one line of context, and -- separates the two groups. In the second, -B 2 shows what happened just before the timeout. The third prints one line on each side and drops the separator.

Options

OptionEffect
-A N, --after-context=NN lines after each match
-B N, --before-context=NN lines before each match
-C N, --context=N, -NN lines before and after; -2 is the same as -C 2
-nLine numbers; 12: for a match, 12- for a context line
--group-separator=TEXTPrint TEXT instead of -- between groups (GNU)
--no-group-separatorNo line between groups (GNU)
-m NStop after N matching lines; trailing context is still printed
--color=alwaysHighlight the match, also when the output goes to a pipe such as less -R

How overlapping context is handled

When the context of two matches overlaps or touches, grep merges them into one group and prints each line once; there is no -- between them. This is why -C 5 on a log with many matches can print long blocks without separators. If every match must be shown with its own context, use a different tool (for example awk) because grep never repeats lines.

Context in several files

bash
printf 'a\nTODO fix\nb\n' > one.txt
printf 'c\nd\nTODO test\n' > two.txt
grep -n -B 1 TODO one.txt two.txt

Output

one.txt-1-a
one.txt:2:TODO fix
--
two.txt-2-d
two.txt:3:TODO test

With more than one file, every line starts with the file name. Matching lines use file:line: and context lines file-line-, which keeps the output parseable.

Platform notes

The options above are in GNU grep and in the BSD grep that ships with macOS; -A, -B and -C are not in POSIX, so very small systems (BusyBox builds without them) may lack them. If no line matches, grep prints nothing and exits with status 1, whatever the context options.

FAQ

How do I remove the -- lines between groups?

GNU grep prints -- between groups of context that are not adjacent. Add --no-group-separator to drop them, or --group-separator=TEXT to print something else. Both are GNU options; with another grep, filter the separator out with grep -v '^--$'.

Can I show context for only the first match?

Yes, combine -m 1 with the context option, grep -m 1 -A 5 pattern file. grep stops after the first matching line but still prints its trailing context.

How do I see the lines after a match in a live log?

tail -f app.log | grep --line-buffered -A 3 ERROR. --line-buffered makes grep print each line as soon as it arrives instead of waiting for its output buffer to fill.

Sources