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'.


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 '11 at 16:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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