loading...
Cover image for Seeing Context with `grep`

Seeing Context with `grep`

rpalo profile image Ryan Palo Originally published at assertnotmagic.com ・3 min read

Have you ever searched for some text in a file on the command line only to realize that grep's output isn't quite enough for you to understand what is happening in the file? Sometimes you want to see some extra lines or even the whole file with your search terms highlighted.

To See a Few Lines

You can use the -A, -B, and -C flags to see a few lines of context. -A <number> will show "number" lines after each match, -B <number> will show "number" lines before a match, and -C <number> shows "number" lines both before and after. It helps to remember After, Before, and Context. grep -C 5 ... is equivalent to grep -A 5 -B 5 .... I actually like to add the -n flag as well to show 1-indexed line numbers, because it helps me find the spot in the file later.

Here they are in action:

# inside example.txt
If you are a dreamer, come in,
If you are a dreamer, a wisher, a liar,
A hope-er, a pray-er, a magic bean buyer…
If you’re a pretender, come sit by my fire
For we have some flax-golden tales to spin.
Come in!
Come in!

- Shel Silverstein
$ grep -A 3 "fire" example.txt
If you’re a pretender, come sit by my fire
For we have some flax-golden tales to spin.
Come in!
Come in!

$ grep -B 2 -n "golden" example.txt
3-A hope-er, a pray-er, a magic bean buyer…
4-If you’re a pretender, come sit by my fire
5:For we have some flax-golden tales to spin.

$ grep -C 1 -n "bean" example.txt
2-If you are a dreamer, a wisher, a liar,
3:A hope-er, a pray-er, a magic bean buyer…
4-If you’re a pretender, come sit by my fire

To See the Whole File

A trick to see the whole file is to match a non-printing character that is in every line, like the line start or end.

grep -e '^' -e 'magic' example.txt

Results showing the whole file but with the word "magic" highlighted in color.

Although, that's abusing grep a little bit. A better way might be to use the neat search functions of less. Run less example.txt and then type / followed by your search term. If you type /magic<Enter>, you see something like this:

Less showing the whole file with the word "magic" highlighted.

Nobody: ...

Vim users: YoU cAn Do ThE sAmE tHiNg In ViM!

*I'm kidding. I love vim and use this feature all the time.

But There's No Color on Mine!

There's a --color option for grep. In fact, there's even a --colour convenience option for those so inclined! It can take the values "never", "always", or "auto". "Auto" will colorize the output if it is being output to a terminal, but drop the colors if the output is getting piped to another command or a file. This is because the colors are coded as characters right into the output text, and they'll show up in plaintext output files and other programs like less. You'll see a lot of StackOverflow answers recommending --color=always, but that will give you those weird color code characters and is not probably what you want.

So try running:

grep --color=auto -e '^' -e 'my search term' data.txt

If that works, you might consider putting this line in your .bashrc file:

export GREP_COLORS="auto"

This will keep you from having to type it every time.

Posted on by:

rpalo profile

Ryan Palo

@rpalo

Ryan is an engineer in the Sacramento Area with a focus in Python, Ruby, and Rust. Bash/Python Exercism mentor. Coding, physics, calculus, music, woodworking. Message me on DEV!

Discussion

markdown guide
 

Meta advice: "tldr" (tldr.sh/) is a wonderful, pragmatic way to find common flags for commands. It's much more approachable than man.

$ tldr grep

grep

Matches patterns in input text.
Supports simple patterns and regular expressions.

- Search for an exact string:
    grep search_string path/to/file

- Search in case-insensitive mode:
    grep -i search_string path/to/file

- Search recursively (ignoring non-text files) in current directory for an exact string:
    grep -RI search_string .

- Use extended regular expressions (supporting `?`, `+`, `{}`, `()` and `|`):
    grep -E ^regex$ path/to/file

- Print 3 lines of [C]ontext around, [B]efore, or [A]fter each match:
    grep -C|B|A 3 search_string path/to/file

- Print file name with the corresponding line number for each match:
    grep -Hn search_string path/to/file

- Use the standard input instead of a file:
    cat path/to/file | grep search_string

- Invert match for excluding specific strings:
    grep -v search_string


 
 

It's best to also use them in conjunction:

Use tldr for the quick easy things, then with that knowledge, you know what to look for in the man page.

 

Nice! That’s a neat service. Thanks for sharing!

 

If I remember correctly, you can install tldr locally on your PC.

 

Nicely presented!

Suggestion: as a good practice, always use single quotes unless you need double quotes (you've mixed it up in the article)

With GNU grep, you have two options to control how to separate different matching groups: --no-group-separator and --group-separator (see my tutorial for details)

As pointed by others, ripgrep has --passthru option to show entire input file instead of using regex trick. You can also use -E '^|pattern' or -E 'pattern|$' instead of -e option. always color option is useful to highlight multiple terms in different color, see stackoverflow.com/questions/172360... for example

For those interested in detailed learning of GNU grep and ripgrep, I have a book on that: github.com/learnbyexample/learn_gn... (I had a free offer running, but that ended yesterday, bad timing)

 

Very helpful, thanks! I appreciate the input from someone who literally wrote the book.

The —always tip is especially good, because I was not sure that there was ever a good reason for that option. The -e choice of syntax was deliberate, as I think it gives an ever so slight readability boost over the more opaque regex syntax for showing separate patterns, but showing folks that the extended regex flag is available is a good tip. Thanks again!

 

2nd Meta advice: grep is awfully slow, there are many replacement such as The Platinum Searcher or - my personal favourite - RipGrep. Both support almost the same options as grep, so switching from grep to one of those program will be easy.

 

An even better way of "seeing the whole file" is to use cat... though if you only want a page or screenful at a time then less is definitely more.

 

Does cat do search highlighting?

 

No, because that's not its job. If you want search highlighting use a colourised grep. If you just want to see the whole file, use cat. Do one thing, do it well.

Yeah cool, just checking. Thanks for clarifying. This post was mostly about different ways to see more of the file as you searched for specific things, but you are right that if all you want to do is see the contents of the file, cat is the best option for short files. I appreciate the addition!

 
 

As an aside, ripgrep and ack can do what you want with the --passthru flag:

rg --passthru magic example.txt
 
 

What about ack? Once I discovered ack-grep I never went back.

 

You can omit the -A -B -C and just go for

grep -n4 pattern file

To get indexed result with 4 lines above and below