Colorized anagrams.gnu.sed

    #n
    #! /bin/sed -nf

    # Search for anagrams in a line-feed-delimited (i.e. one word per line)
    # list of words

    H

    # Sort the letters of the word (preceding it with a @)
    s/$/@/
    t z
    :z
    s/\(z\+\)\(.*@\)/\2\1/
    t z
    :y
    s/\(y\+\)\(.*@\)/\2\1/
    t y
    :x
    s/\(x\+\)\(.*@\)/\2\1/
    t x
    :w
    s/\(w\+\)\(.*@\)/\2\1/
    t w
    :v
    s/\(v\+\)\(.*@\)/\2\1/
    t v
    :u
    s/\(u\+\)\(.*@\)/\2\1/
    t u
    :t
    s/\(t\+\)\(.*@\)/\2\1/
    t t
    :s
    s/\(s\+\)\(.*@\)/\2\1/
    t s
    :r
    s/\(r\+\)\(.*@\)/\2\1/
    t r
    :q
    s/\(q\+\)\(.*@\)/\2\1/
    t q
    :p
    s/\(p\+\)\(.*@\)/\2\1/
    t p
    :o
    s/\(o\+\)\(.*@\)/\2\1/
    t o
    :n
    s/\(n\+\)\(.*@\)/\2\1/
    t n
    :m
    s/\(m\+\)\(.*@\)/\2\1/
    t m
    :l
    s/\(l\+\)\(.*@\)/\2\1/
    t l
    :k
    s/\(k\+\)\(.*@\)/\2\1/
    t k
    :j
    s/\(j\+\)\(.*@\)/\2\1/
    t j
    :i
    s/\(i\+\)\(.*@\)/\2\1/
    t i
    :h
    s/\(h\+\)\(.*@\)/\2\1/
    t h
    :g
    s/\(g\+\)\(.*@\)/\2\1/
    t g
    :f
    s/\(f\+\)\(.*@\)/\2\1/
    t f
    :e
    s/\(e\+\)\(.*@\)/\2\1/
    t e
    :d
    s/\(d\+\)\(.*@\)/\2\1/
    t d
    :c
    s/\(c\+\)\(.*@\)/\2\1/
    t c
    :b
    s/\(b\+\)\(.*@\)/\2\1/
    t b
    :a
    s/\(a\+\)\(.*@\)/\2\1/
    t a

    # After this second H command, we added to the hold space <word>\n@<signature>
    # We'll remove the extra newlines later
    H

    $ {
        # Append a final line feed to hold space, change \n@ to @
        s/.*//
        H
        g
        s/\n@/@/g
        h

        t loop
        :loop
        # Search two words with the same signature and print them
        # \1 = first word
        # \2 = signature
        # \3 = anything in the middle (not backref'ed, needed for \?)
        # \4 = second word
        s/^.*\n\([a-z]*\)@\([a-z]*\)\n\(.*\n\)\?\([a-z]*\)@\2\n.*$/\1 \4/p
        g

        # Remove the second of the two words with the same signature
        # so we'll print n-1 pairs instead of n(n-1)/2
        # \1 = anything before
        # \2 = first word @ signature
        # \3 = signature
        # \4 = anything in the middle (not backref'ed, needed for \?)
        # \5 = anything after
        #
        # We need to use \1 and \5 to make sure we remove exactly the same
        # pair that we printed above
        s/^\(.*\)\(\n[a-z]*@\([a-z]*\)\n\)\(.*\n\)\?[a-z]*@\3\n\(.*\)$/\1\2\4\5/
        h

        # Look for another anagram if we did find one
        t loop
    }

    ### colorized by sedsed, a debugger and code formatter for sed scripts