One way using GNU sed for your second scenario, althought it seems a bit complex (it's fully commented):
Assuming infile has following content:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
And content of script.sed:
## From first line until a line that matches the pattern (number ten in
## this example), save lines in buffer and print each one when there are
## more than three lines between one of them and the line with the pattern
## to search.
0,/10/ {
## Mark 'a'
:a
## If line matches the pattern break this loop.
/10/ {
bb
}
## Until the pattern matches, if more than three lines (checking '\n') are
## saved, print the oldest one and delete it, because I only want to save last
## three.
/\(\n[^\n]*\)\{3\}/ {
P
D
}
## Append next line to pattern space and goto mark 'a' in a loop.
N
ba
}
## It should never match (I think), but it's a sanity check to avoid the
## following mark 'b'.
bc
## Here we are when found the line with the pattern, so read next five six
## lines and delete all of them but the sixth. If end of file found in this
## process none of them will be printed, so it seems ok.
:b
N;N;N;N;N
N
s/^.*\n//
## Here we are after deleting both '-3' and '+5' lines from the pattern matched,
## so only is left to print the remainder of the file in a loop.
:c
p
N
s/^.*\n//
bc
Run it like this having into account that 10 is the pattern both in fifth and eleventh lines of code. Change it to your needs. In my example it should delete lines 7,8,9,10,11,12,13,14,15:
sed -nf script.sed infile
With following output:
1
2
3
4
5
6
16
17
18
19
20