LL Golf #1 - tinyurl.comを使ったURLの短縮

LL Golf - Hole 1 がついにスタートしました。 去年は私が担当だったのですが、RSS が配信されなかったりして盛り上がりにかけてしまって申し訳なかったと思っています。 今年は LL スタッフの中でも U-30 世代の方々を中心にお題を出してもらうことになっています。 またどう書く?org をお借りすることになりました。

さて、お題はLL Golf #1 - tinyurl.comを使ったURLの短縮です。

tinyurl.com( http://tinyurl.com/ )のサービスを利用し、
http://ll.jus.or.jp/2008/info/xgihyo というURLを短縮しなさい。
tinyurl.comのalias機能は使わないものとする。なお、参考までに短縮したURL
は http://tinyurl.com/5mngx8 となる。

ということです。

ちょっとだけ紳士的に

紳士な方は、

$ GET 'http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo'

とかを言ってはいけません。(w

$ GET http://easyurl.jp/edz

とかもいけません。

しかしながら、nawk, mawk など TCP での通信をサポートしていない awk は上記手法に頼らなければいけません。 したがって、

$ GET 'http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo' | awk '1'

のようになるわけですが、「awk だと Golf 最短 1 byte だぜ」とか言ってはいけません。

また、うまく動かせていないのですが、awk4j を用いることで以下のようにすることができるようです。

$ awk4j '1' 'http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo'

はい。完全に 1 byte です。

ここまで空気の読めない記述ですが、実際に awk で使いたいというような場合というのは、何か標準入力から URL がリアルタイムに流れ込んでくる中でリアルタイムで TinyURL を使いたいというような場合だと思います。 ですから、ここではawk でリファラ解析の際に用いたスクリプトに組み込んでみたいと思います。

Apache のリファラを TinyURL で

最初に例を挙げておきます。

#! /usr/bin/gawk -f
# doukaku_tinyurl_1.awk

BEGIN {
    FS = "\"";
    my_url = "http://gauc.no-ip.org/";
}

$4 !~ my_url && $4 != "-" {
    printf("%s -> ", $4);
    system("GET 'http://tinyurl.com/api-create.php?url=" $4 "'");
    print "";
}

実際に動かしてみましょう。

$ sudo tail -f /var/log/httpd/access_log | gawk -f doukaku_tinyurl_1.awk
http://b.hatena.ne.jp/entry/8720355 -> http://tinyurl.com/5jmzvb

system() 関数は Golf ではご法度とされていますが、system() 関数を用いることで fflush() 関数の代用をしています。 gawk の TCP 通信を用いた場合には tail -f からの標準入力を fflush() しないと途中で止まってしまうのです。 これはあまりにも便利なので覚えておくと良いと思います。

しかし、リファラを TinyURL で返しても今ひとつ面白くありません。 やはり TinyURL が最も使われるのは Twitter のような文字数に制限があるものではないでしょうか?

超実用! awk でコマンドラインから Twitter 投稿

実用! awk でコマンドラインから Twitter 投稿には TinyURL 変換が含まれてません。 これに組み込んでしまえば、今私がやっているような Firefox の TinyUrl Creator を使う必要もないわけです。 LL とはこういうことのためにこそ存在意義があるのです。 また、コマンド間の仲介として awk を使うことは awk の使い方として間違っていないと思います。

まず URL を正規表現にしようと思い、ググればいくらでもヒットしますが、Twitter で URL を送るのは大体送信文書の最後ですから、簡単にするため http:// 以下を全て URL と見なしてしまいましょう。

ここでは wget コマンドを用います。 wget コマンドは Web 上のものを GET するだけでなく、Twitter で用いられている BASIC 認証や PUT の機能もありますので、「餅は餅屋」に任せるのも awk らしい使い方と言えます。

#! /usr/bin/gawk -f
# doukaku_tinyurl_2.awk

BEGIN {
    twitter_id   = "**********";    # 自分の ID にしてください
    twitter_pass = "**********";    # 自分のパスワードにしてください
}

{
    url_start = length($0) + 1;
    tiny_url = "";

    if (match($0, /http:\/\//)) {
        url = substr($0, RSTART);
        url_start = RSTART;
        "GET 'http://tinyurl.com/api-create.php?url=" url "'" | \
             getline tiny_url;
    }
    twitter_post_cmd = "wget --user=" twitter_id " --password=" twitter_pass \
                       " --post-data=status='" substr($0, 1, url_start - 1) \
                       " " tiny_url \
                       "' http://twitter.com/statuses/update.json" \
                       " 2> /dev/null";
    system(twitter_post_cmd);
    system("rm update.json*");
}

実行してみましょう。

$ gawk -f doukaku_tinyurl_2.awk
LL Golf #1 - tinyurl.comを使ったURLの短縮 http://gauc.no-ip.org/awk-users-jp/blis.cgi/DoukakuAWK_039

DoukakuAWK_039.png

標準入力から受け付けるようになっていますから、そのままメッセーjを入れていくだけです。 実際に Twitux の画面にはちゃんと TinyURL を通した URL が表示されていることが分かります。

と、逆に問題を無視して空気が読めていないのは私かもしれませんが、かなり面白いプログラムができあがったと思っています。 他に何かアイデアを思いつけば書き足していきます。

  • いろいろミスがあって修正入れました。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png