Description
A `sliding-window' approach is used:\
  • The window can hold at most N lines.
  • The lines in the window are candidates for deletion.
  • The window initially holds the first N lines of the datafile.
  • If the window is full and we want to insert a new line into it, the line with the lowest line number should leave, and then
    the new line enters.
  • The line leaving the window is NOT a candidate for deletion, so just print it.
  • When the end of the datafile is reached, print the last (M-1) lines of the window and delete the others.
We also have to take into account the case when the datafile contains less than N lines:
  • If a file contains less than M lines, every line of the file must be printed.
  • If a file contains at least M but less N lines, lines after the last M-th line must be printed.
The following example deletes the last 7th(N=7) till the last 3rd(M=3) lines.
Raw Input Desired Output
Line 10
Line 9
Line 8
Line 7
Line 6
Line 5
Line 4
Line 3
Line 2
Line 1
Line 10
Line 9
Line 8
Line 2
Line 1
Script and Comments
Script1
[ 1] :loop
[ 2] 1,N-1{
[ 3] $b last
[ 4] N
[ 5] b loop
[ 6] }
[ 7] $!{
[ 8] N
[ 9] P
[10] D
[11] }
[12] :last
[13] s/^.*\n([^\n]*(\n[^\n]*){M-2})$/\1/
Comments -r
  1. Steps [1] thru [6] constitute a loop which reads the first N lines to PS.
  2. PS is used as the sliding window (abbreviated to SW).
  3. Steps [7] thru [10] constitute a loop which
    • Step [8] appends the next line to SW,
    • Step [9] prints the first line of SW,
    • Step [10] deletes the first line of SW,
      then sed jumps to Step [1], [2] then [7] since the current line is not one of the first (N-1) lines of the datafile.
  4. Step [13] deletes all but the last (M-1) lines of SW.
Script2
[ 1] :loop
[ 2] 1,6{
[ 3] $b last
[ 4] N
[ 5] b loop
[ 6] }
[ 7] $!{
[ 8] N
[ 9] P
[10] D
[11] }
[12] :last
[13] s/^.*\n([^\n]*\n[^\n]*)$/\1/
Comments -r
  1. A script that works for N=7 and M=3.