Description
In this example, we want to get every 4th line of a file, i.e., 4th line, 8th line, 12th line, and so on.
Raw Input Desired Output
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10
line 11
line 12
line 13
line 14
line 15
line 4
line 8
line 12
Script and Comments
Script1
[ 1] :loop
[ 2] $!{
[ 3] N
[ 4] /(\n[^\n]*){3}/!b loop
[ 5] }
[ 6] s/^([^\n]*\n){3}([^\n]*)/\2/p
[ 7] d
Comments -r
  1. Steps [1] thru [4] constitute a loop which keep appending lines to PS until there are 4 lines:
    • Command `N' of Step [3] appends a newline character, followed by the next line to PS.
    • If PS has few than 4 lines, make sed jump to Step [1].
    • In Step [2], `$' matches only when the current line is the last line of a file; `!' indicates a negation.
  2. In Step [6], if PS has exactly 4 lines, we delete the first 3 and keep the last one. The flag `p' will print the contents of PS if the substitution succeeds.
  3. Step [7] deletes the contents of PS and start a new cycle.
Script2
[ 1] :loop
[ 2] $!N
[ 3] s/^([^\n]*\n){3}([^\n]*)/\2/
[ 4] t
[ 5] $!b loop
[ 6] d
Comments
  1. A neat version.
  2. If PS has 4 lines,
    • the RE of Command `s' of Step [3] will match, and
    • Command `t' of Step [4] will make sed jump to the end of this script, print the contents of PS, then start a new cycle.
  3. Otherwise, Step [5] will make sed jump to Step [1] if the last line has not been reached.