Here's another way with
sed '/foo/,$!d;H;/bar/!d;s/.*//;x;s/\n//' infile
It appends each line in
/foo/,$ range (lines
! not in this range are
Hold space. Lines not matching
bar are then deleted. On lines that match, the pattern space is emptied, e
xchanged with the hold space and the leading empty line in the pattern space is removed.
With huge input and few occurrences of
bar this should be (much) faster than pulling each line into pattern space and then, each time, checking the pattern space for
sed '/foo/,$!d # delete line if not in this range
H # append to hold space
/bar/!d # if it doesn't match bar, delete
s/.*// # otherwise empty pattern space and
x # exchange hold buffer w. pattern space then
s/\n// # remove the leading newline
Sure, if this is a file (and fits in memory) you could simply run:
ed -s infile<<'IN'
ed can search forward and backward.
You could even read a command output into the text buffer if your shell supports process substitution:
printf '%s\n' .t. /foo/,?bar?p q | ed -s <(your command)
or if it doesn't, with
printf '%s\n' .t. /foo/,?bar?p q | ed -s '!your command'