Is there a way, either with grep or something else, to (in effect) combine grep -v and grep -A? That is, rather than include everything for x lines after a string, exclude everything.

Quick reminder for those who forget their grep switches:
cat file.txt | grep -v blah filters out 'blah', the opposite of normal grep
cat file.txt | grep -A7 foo will display 7 lines after each occurance of 'foo'
(Yes I'm aware that cat is unnecessary here. But I find it much more readable when you string together a lot of grep statements to do it this way.)

Simply saying
cat file.txt | grep -A100 bar | grep -vA100 foo
will not work. "Working" would be defined as displaying everything (up to 100 lines) between the line matching 'bar' and the line matching 'foo'.

1 Answer 1


There's a simple way of extracting all chunks from a bar to a foo with sed:

sed -n '/bar/,/foo/p'

or with awk:

awk '/bar/, /foo/'

If you want to truncate the chunks, it's a little more complicated (in awk; in sed it's a lot more complicated). Here's a solution:

awk -vmax_lines_per_chunk=100 '
    /bar/ {n=max_lines_per_chunk}
    /foo/ {if (n) print; n=0}
    n {--n; print}
  • An interesting difference between the simple sed and awk versions: the awk version stops at bar if foo also matches bar. For example, imagine this inside a function: cat ~/.ssh/config | awk "/Host ${1}$/, /Host /" to get everything from the line with Host and $1 up until the next line with Host. awk sees that the first line matches foo and stops there. It makes perfect sense, of course, but sed fits my needs better here.
    – iconoclast
    Jul 25, 2011 at 16:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .