This question already has an answer here:

Say I have file:


If I run cat file | grep dog -B 1 I get:


If I run cat file | grep dog -v I get:


I would expect cat file | grep dog -v -B 1 to return bird but instead it just acts like grep dog without any flags.

Why can't I use these flags together?

grep (GNU grep) 2.16, also tested on 2.25 with same results

marked as duplicate by don_crissti, Philip Kirkbride, Community Nov 16 '17 at 14:40

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Which grep? GNU grep 3.1 gives me all three lines in the output, as expected. – muru Nov 16 '17 at 14:12
  • @muru Shouldn't cat file | grep dog -v -B 1 return just bird instead of all three lines? I'm using 2.16. – Philip Kirkbride Nov 16 '17 at 14:14
  • Why only bird? It should of course return cat (and since there's nothing before it, nothing more for cat), and for bird, bird and the line above it, which is dog, hence, all three lines. – muru Nov 16 '17 at 14:17
  • Compare: (seq 1 5; seq 5 10) | grep 5 -B 1 -v skips the first 5 in the output for me. – muru Nov 16 '17 at 14:19
  • How about this: cat test.txt| grep dog -A 1 | awk '{if (NR!=1) {print}}' – Arpit Agarwal Nov 16 '17 at 15:04

I just wanted to add my solution to get the inverse of grep dog -B 1:

cat file | grep "$(cat file | grep dog -B 1)" -v

Which returns bird the opposite of what cat file | grep dog -B 1 produces.

It seems my original problem was just misunderstanding how this should work. I was thinking applying -v would simply inverse any grep command.

In actuality it seems the -v flag was run first and then -B 1 is applied after, so all lines not containing dog are returned and then all lines 1 before those lines, meaning all lines.

Edit: I realized this solution is wrong. It doesn't inverse because the second grep using the sub-shell doesn't treat "$(cat file | grep dog -B 1)" as a single text block. Instead each line generated is treated as a different grep.

If the subshell includes:


And the original file includes other instances of cat that aren't 1 position before dog they will be removed to with this solution.

  • @don_crissti looks like OP wants -A1, but without the line that matched. – muru Nov 16 '17 at 14:29
  • @don_crissti I simply want to return the opposite of grep commands using -A -B or -C flags. Whatever text a grep -B $n produces I want all lines that weren't shown instead of those that were. Does that make sense? – Philip Kirkbride Nov 16 '17 at 14:34
  • 1
    @don_crissti closed – Philip Kirkbride Nov 16 '17 at 14:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.