OSC2011 Tokyo/Fall 特設サイト

オープンソースカンファレンス2011 Tokyo/Fall - オープンソースの文化祭! に来ていただき、ありがとうございます。 AWK Users JP :: 日本 GNU AWK ユーザー会 では USP友の会 と有効団体になったことを受け、合同セッションならびに隣り合わせのブースで shell と awk について紹介します。

「シェルスクリプト VS AWK」 どっちが強い!?プログラミングバトル

11/19 (土) の 16:15 から オープンソースカンファレンス2011 Tokyo/Fall - イベント案内 | 2011-11-19 (土): 「シェルスクリプト VS AWK」 どっちが強い!?プログラミングバトル にて USP友の会 の会長の上田さんと合同のセッションを行います。 簡単な例を用いて awk の良さ、shell の良さをそれぞれ感じてもらえると嬉しいです。

また、良く分からなかった内容や質問に関しては、ブースにて対応させていただきます。 もちろん「USP 友の会」と隣り合わせのブースになっています。

もしもブースにいない場合には、Twitter にて @hi_saito に連絡してください。

awk で簡単な CGI

セッションでは紹介しきれない、awk を使った CGI のサンプルを以下に置いておきます。 以下の CGI は体重 (0 〜 100 Kg) を入力すると、Gnuplot でグラフを生成する CGI です。

ブース展示 gawk + ImageMagick

「AWK で宛名書き」というと単なるテキストでタグシートに印刷するようなイメージを持たれている方も多いと思いますが、ここでは TrueType フォントを用いて、あたかも年賀状ソフトのように表現できることを目指しました。 ここに掲載したものは、あくまでモックアップでしかありませんが、AWK で記述されているため、これらを元に加工することも簡単だと思います。

住所録は CSV で保存し、テキスト処理のみを AWK で行い、TrueType フォントや画像として出力する部分を ImageMagick を使ったものです。 gawk も ImageMagick も一般的な Linux ディストリビューションに含まれていますので、導入することが簡単です。

#! /usr/local/bin/gawk -f
# hagaki.awk

BEGIN {
    # CSV ファイルを扱う
    FS = ",";
}

# 1 行目に自分の住所を記述
NR == 1 {
    my_name_1       = $1;       # 自分の苗字
    my_name_2       = $2;       # 自分の名前
    my_sir_1        = $3;       # 自分の敬称 (未使用)
    my_name_3       = $4;       # 連名
    my_sir_2        = $5;       # 連名の敬称 (未使用)
    my_zip          = $6;       # 自分の郵便番号
    my_address_1    = $7;       # 自分の住所 1 (市町村)
    my_address_2    = $8;       # 自分の住所 2
    my_address_3    = $9;       # 自分の住所 3 (マンション等)
    my_phone        = $10;      # 電話番号 (未使用)
}

# 2 行目以降に相手の住所を記述
NR != 1 {
    name_1          = $1;       # 苗字
    name_2          = $2;       # 名前
    sir_1           = $3;       # 敬称
    name_3          = $4;       # 名前 (連名)
    sir_2           = $5;       # 敬称
    zip             = $6;       # 郵便番号
    address_1       = $7;       # 住所 1 (市町村)
    address_2       = $8;       # 住所 2
    address_3       = $9;       # 住所 3 (マンション等)
    phone           = $10;      # 電話番号 (未使用)

    # 郵便番号を処理
    gsub(/-/, "", zip);
    num_zip             = split(zip, \
                            char_zip, "");
    zip_cmd             = text2img(char_zip, \
                            "horizontal", 522, 205, 85, 48);

    # 住所 1 を処理
    gsub(/ /, "", address_1);
    num_address_1       = split(trans_kanji_wide_char(address_1), \
                            char_address_1, "");
    address_1_cmd       = text2img(char_address_1, \
                            "vertical", 1050, 400, 75, 70);

    # 住所 2 を処理
    gsub(/ /, "", address_2);
    num_address_2       = split(trans_kanji_wide_char(address_2), \
                            char_address_2, "");
    address_2_cmd       = text2img(char_address_2, \
                            "vertical", 950, 500, 75, 70);

    # 住所 3 を処理
    gsub(/ /, "", address_3);
    num_address_3       = split(trans_kanji_wide_char(address_3), \
                            char_address_3, "");
    address_3_cmd       = text2img(char_address_3, \
                            "vertical", 850, 500, 75, 70);

    # 苗字を処理
    gsub(/ /, "", name_1);
    num_name_1          = split(trans_kanji_wide_char(name_1), \
                            char_name_1, "");
    name_1_cmd          = text2img(char_name_1, \
                            "vertical", 600, 400, 160, 150);

    # 名前を処理
    gsub(/ /, "", name_2);
    num_name_2          = split(trans_kanji_wide_char(name_2), \
                            char_name_2, "");
    name_2_cmd          = text2img(char_name_2, \
                            "vertical", 600, 900, 160, 150);

    # 敬称を処理
    gsub(/ /, "", sir_1);
    num_sir_1           = split(trans_kanji_wide_char(sir_1), \
                            char_sir_1, "");
    sir_1_cmd           = text2img(char_sir_1, \
                            "vertical", 600, 1400, 160, 150);

    # 連名を処理
    gsub(/ /, "", name_3);
    num_name_3          = split(trans_kanji_wide_char(name_3), \
                            char_name_3, "");
    name_3_cmd          = text2img(char_name_3, \
                            "vertical", 400, 900, 160, 150);

    # 連名の敬称を処理
    gsub(/ /, "", sir_2);
    num_sir_2           = split(trans_kanji_wide_char(sir_2), \
                            char_sir_2, "");
    sir_2_cmd           = text2img(char_sir_2, \
                            "vertical", 400, 1400, 160, 150);

    # 自分の郵便番号を処理
    gsub(/-/, "", my_zip);
    num_my_zip          = split(my_zip, \
                            char_my_zip, "");
    my_zip_cmd          = text2img(char_my_zip, \
                            "horizontal", 50, 1470, 50, 48);

    # 自分の住所 1 を処理
    gsub(/ /, "", my_address_1);
    num_my_address_1    = split(trans_kanji_wide_char(my_address_1), \
                            char_my_address_1, "");
    my_address_1_cmd    = text2img(char_my_address_1, \
                            "vertical", 300, 700, 55, 50);

    # 自分の住所 2 を処理
    gsub(/ /, "", my_address_2);
    num_my_address_2    = split(trans_kanji_wide_char(my_address_2), \
                            char_my_address_2, "");
    my_address_2_cmd    = text2img(char_my_address_2, \
                            "vertical", 240, 800, 55, 50);

    # 自分の住所 3 を処理
    gsub(/ /, "", my_address_3);
    num_my_address_3    = split(trans_kanji_wide_char(my_address_3), \
                            char_my_address_3, "");
    my_address_3_cmd    = text2img(char_my_address_3, \
                            "vertical", 180, 800, 55, 50);

    # 自分の苗字を処理
    gsub(/ /, "", my_name_1);
    num_my_name_1       = split(trans_kanji_wide_char(my_name_1), \
                            char_my_name_1, "");
    my_name_1_cmd       = text2img(char_my_name_1, \
                            "vertical", 100, 900, 65, 60);

    # 自分の名前を処理
    gsub(/ /, "", my_name_2);
    num_my_name_2       = split(trans_kanji_wide_char(my_name_2), \
                            char_my_name_2, "");
    my_name_2_cmd       = text2img(char_my_name_2, \
                            "vertical", 100, 1100, 65, 60);

    # 自分の連名を処理
    gsub(/ /, "", my_name_3);
    num_my_name_3       = split(trans_kanji_wide_char(my_name_3), \
                            char_my_name_3, "");
    my_name_3_cmd       = text2img(char_my_name_3, \
                            "vertical", 20, 1100, 65, 60);

    system("convert postcard.jpg -font tanuki.ttf " \
            zip_cmd " " \
            address_1_cmd " " \
            address_2_cmd " " \
            address_3_cmd " " \
            name_1_cmd " " \
            name_2_cmd " " \
            sir_1_cmd " " \
            name_3_cmd " " \
            sir_2_cmd " " \
            my_zip_cmd " " \
            my_address_1_cmd " " \
            my_address_2_cmd " " \
            my_address_3_cmd " " \
            my_name_1_cmd " " \
            my_name_2_cmd " " \
            my_name_3_cmd " test.png");

}

# ImageMagick のコマンドへの変換
function text2img(arr, direction, init_pos_x, init_pos_y, pitch, font_size,\
    text, coo_x, coo_y, str_text, arr_text, i, idx, draw_str) {

    str_text = "ぁぃぅぇぉゃゅょっァィゥェォャュョッ。、";
    split(str_text, arr_text, "");

    for (i = 1; i <= length(arr); i++) {
        text = arr[i];
        coo_x = (direction == "vertical" ? init_pos_x : \
                init_pos_x + pitch * (i - 1));
        coo_y = (direction == "horizontal" ? init_pos_y : \
                init_pos_y + pitch * (i - 1));

        for (idx in arr_text) {
            if (text == arr_text[idx]) {
                coo_x = coo_x + font_size / 3;
            }
        }

        draw_str    = draw_str " -draw \"text " coo_x "," coo_y \
                        " '" text "'\"";

    }

    return " -pointsize " font_size " " draw_str;
}

# 漢数字への変換
function trans_kanji_wide_char(str) {
    str = gensub(/0/, "〇", "g", str);
    str = gensub(/1/, "一", "g", str);
    str = gensub(/2/, "二", "g", str);
    str = gensub(/3/, "三", "g", str);
    str = gensub(/4/, "四", "g", str);
    str = gensub(/5/, "五", "g", str);
    str = gensub(/6/, "六", "g", str);
    str = gensub(/7/, "七", "g", str);
    str = gensub(/8/, "八", "g", str);
    str = gensub(/9/, "九", "g", str);
    str = gensub(/-/, "|", "g", str);
    str = gensub(/ー/, "|", "g", str);

    return str;
}

実際に用いたデモをご用意しました。