#n
#! /bin/sed -nf
#----------------- gather the lines in hold space
H
$ !b
#----------------- sort them
# Append a new-line and the look-up table to hold space, get everything
# in pattern space
s/.*/° !"#$%\&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/
H
g
t sort
:sort
# This regexp performs an insertion sort pass!!!
# It searches for two lines with a common (possibly empty) prefix and
# compares the first differing char using a lookup table -- if the
# order is wrong, the regexp matches and the RHS of the s command
# swaps the lines
#
# \1 = line after the one to be inserted
# \2 = common part to the two lines
# \3 = first differing char (in \1)
# \4 = lines between the two lines
# \5 = line to be inserted
# \6 = first differing char (in \5)
# \7 = lines after the second line + the lookup table
s/\(\n\([ -~]*\)\([ -~]\)[ -~]*\)\(\n.*\)\?\(\n\2\([ -~]\)[ -~]*\)\(\n.*°.*\6.*\3\)/\5\1\4\7/
# 1---------------------------- 4--- 5------------------ 7------------
# 2----- 3---- 6----
t sort
# Remove the last new-line and the lookup table
# Leave the leading new-line
s/^\(.*\)\n°.*$/\1/
# ----------------- delimit and number them
:number
# Remove the first line, move the last number to the beginning of the
# new first line together with the lookup table
s/\([0-9]*\)[ -~]*\n/\1;9876543210990090 /
# This regexp does the incrementing -- see tutorials for its explanation
s/\([0-8]\{0,1\}\)\(9*\);[^1]*\(.\)\1[0-9]*X*\2\(0*\)[^ ]*/\3\4/
P
# If the first char changes, we replace the first line with
# a single new-line character. The pattern space will look the
# same as when we leave the sorting section, and the counter
# will be restarted.
# The leading new-line is printed by the second line, which
# can only match if the first did (if it didn't, the first
# character will still be a digit).
/^[0-9]* \(.\).*\n\1/ !s/[ -~]*//
/^\n/ P
/./ b number
### colorized by sedsed, a debugger and code formatter for sed scripts