Yahoo! Widget の Widget を作っていたときのことです。 バイナリファイルを Base64 にエンコードする必要があったのですが Yahoo! Widget の Windows 版に付属する UnixUtils のコマンドでは今のところそういったコマンドが用意されていません。Mac OS X の Yahoo! Widget ならば Perl とかを使ってゴニョゴニョできるのですが、Windows 環境だとどうすることもできないのということで、Windows の Yahoo! Widget にも付属している gawk を使って変換するスクリプトを作りました。

オリジナルのコードはこちらにあるもので、これを改造しました。
結構高速化をしてみたのですが、それでもWindows 環境で実行するとちょっと遅いですね。。。でもこれを使えば Windows 環境の Yahoo! Widget でもバイナリファイルを Base64 エンコードすることができるようになります!
BEGIN {
    if (ARGC < 2) {
        print "\nEncode an file to BASE64.";
        print "\nUsage: b64enc.awk <filename>\n";
        exit;
    }
    else ARGC = 1;

    BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    result = ""

    for (i = 0; i < 256; i++){
        asc[sprintf("%c", i)] = i
    }

    RS = ""

    while (getline < ARGV[1])
        data = data $0

    while (length(data) > 0) {
        # Specify byte values
        if (length(data) == 1){
            byte1 = asc[substr(data, 1, 1)]
            byte2 = 0
            byte3 = 0
        }
        if (length(data) == 2){
            byte1 = asc[substr(data, 1, 1)]
            byte2 = asc[substr(data, 2, 1)]
            byte3 = 0
        }
        if (length(data) >= 3){
            byte1 = asc[substr(data, 1, 1)]
            byte2 = asc[substr(data, 2, 1)]
            byte3 = asc[substr(data, 3, 1)]
        }

        # Create BASE64 values
        base1 = rshift(byte1, 2)
        base2 = lshift(and(byte1, 3), 4) + rshift(and(byte2, 240), 4)
        base3 = lshift(and(byte2, 15), 2) + rshift(and(byte3, 192), 6)
        base4 = and(byte3, 63)

        # Compose BASE64 string
        if (length(data) == 1){
            result = result substr(BASE64, base1 + 1, 1)
            result = result substr(BASE64, base2 + 1, 1)
            result = result "=="
            data = ""
        }
        if (length(data) == 2){
            result = result substr(BASE64, base1 + 1, 1)
            result = result substr(BASE64, base2 + 1, 1)
            result = result substr(BASE64, base3 + 1, 1)
            result = result "="
            data = ""
        }
        if (length(data) >= 3){
            result = result substr(BASE64, base1 + 1, 1)
            result = result substr(BASE64, base2 + 1, 1)
            result = result substr(BASE64, base3 + 1, 1)
            result = result substr(BASE64, base4 + 1, 1)
            data = substr(data, 4)
        }
    }
    print result
}