Description
Given a file describing the members of groups, where each line may consist of
  • a member's name, or
  • a group's name, followed by a colon `:', then optionally a member's name.
  • blanks are allowed anywhere except between a group's name and the following colon.
We want to reformat the datafile so that each line consists of
  • a group name, followed by a colon `:', a blank, then at most 3 members' names, or
  • a blank, at most 3 member's names.
  • A blank is used to separate two members' names.
Raw Input Desired Output
 adm:
      johnson
      bruce
         miky
             kevin
sales: grace
         joe
          hellen
        may
         ruth
          eric
        cindy
 control: qoo
adm: johnson bruce miky
 kevin
sales: grace joe hellen
 may ruth eric
 cindy
control: qoo
Script and Comments
Script1
[ 1] :0
[ 2] $b 1
[ 3] N
[ 4] /\n.*:/b 1
[ 5] /^( *[^ :]+:)? *([^ :\n]+( +| *\n)){3}/!{
[ 6] s/\n/ /
[ 7] b 0
[ 8] }
[ 9] :1
[10] s/ +/ /g
[11] s/^[^ :\n]+( |$)/ &/
[12] s/^ ([^ :\n]+:)/\1/
[13] P
[14] D
Comments -r
  1. The logic of this script is:
    • Step [3] (command `N') appends the next line to PS. The original PS and the appended line are separated by a newline character.
    • If the original PS consists of
      • a group's name, a colon, and 3 members' names, or
      • only 3 members' names,
      where RE of Step [5], ^( *[^ :]+:)? *([^ :\n]+( +| *\n)){3} matches, the newline character is retained. Then branch to Step [9] to do blank insertion and deletion.
    • Otherwise, Step [6] replaces the newline character with a blank, then branches to Step [1].