Search code examples
regexsed

Calculate the string length in sed


I was forced to calculate the string length in sed. The string is always a nonempty sequence of a's.

sed -n ':c /a/! be; s/^a/1/; s/0a/1/; s/1a/2/; s/2a/3/; s/3a/4/; s/4a/5/; s/5a/6/; s/6a/7/; s/7a/8/; s/8a/9/; s/9a/a0/; /a/ bc; :e p'

It's quite long :) So now I wonder if it is possible to rewrite this script more concisely using the y or other sed command?

I know that it is better to use awk or another tool. However, this is not a question here.

Note that the sed script basically simulates decadic full adder.


Solution

  • I guess it's cheating but:

    sed 's/.//;s/./\n/g'|sed -n '$='
    

    You can certainly shorten your existing version to:

    sed '
    :c
        s/^a/1/
        s/0a/1/
        s/1a/2/
        s/2a/3/
        s/3a/4/
        s/4a/5/
        s/5a/6/
        s/6a/7/
        s/7a/8/
        s/8a/9/
        s/9a/a0/
        tc
    '
    

    Turns out using y/// is possible but I think it only shaves off a few characters, and \u is not portable:

    sed '
    :c
        s/^a/c/
        s/\([b-j]\)a/\u\1/
        y/BCDEFGHIJ/cdefghijk/
        s/ka/ab/
        tc
        y/bcdefghijk/0123456789/
    '
    

    A shorter (probably slower) method using a lookup table:

    sed -E '
    :c
        s/a/<0123456789x1>/
        s/(.?)<.*\1(.).*>/\2/
        s/x/a0/
        tc
    `