awk で喋らせてみる (xgawk 編)

404 Blog Not Found:perl - SayKanji + Yahoo API = itte.pl では Yahoo! API を使って読みを作成していますが、gawk には TCP での通信機能があり、xgawk には XML のパース機能もありますので、xgawk の機能を使って処理してみます。

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

@load xml

BEGIN {
    XMLMODE = 0;
    ORS = RS = "\r\n";
    espeak_cmd = "/usr/bin/espeak";
    espeak_opt = "";

    yahoo_api_base  = "jlp.yahooapis.jp";
    yahoo_api_url   = "FuriganaService/V1/furigana";
    yahoo_api_appid = "your.api";    # 変更してください
    yahoo_api_sentence = ARGV[1];

    # gawk の場合のテンポラリファイルは下記のようにすることで PID を
    # 取得できます
    tmp_file = ENVIRON["TMP"] "/say_japanese_2." PROCINFO["pid"];

    #----------------------------------------------------------------
    # gawk の TCP 通信で Yahoo! API からデータを取得します
    http_url = "/inet/tcp/0/localhost/3128";
    http_str = "GET http://" yahoo_api_base "/" yahoo_api_url \
               "?appid=" yahoo_api_appid \
               "&sentence=" yahoo_api_sentence \
               " HTTP/1.0";

    print http_str     |& http_url;
    print ""           |& http_url;
    while ((http_url |& getline) > 0) {
        if ($0 ~ /<\?xml/) {
            xml_flag = 1;
        }
        if (xml_flag > 0) {
            print $0 > tmp_file;
        }
    }
    close(http_url);
    close(tmp_file);

    #----------------------------------------------------------------
    # ここから xmlgawk の機能で XML をパースします
    XMLMODE    = 1;
    XMLCHARSET = "utf-8";
    ORS = RS = "\n";

    while (getline < tmp_file > 0) {
        # データの格納
        if (XMLCHARDATA) {
            data = $0;
        }
        # 元々英語だった場合 (Roman はセットされません)
        if (XMLENDELEM == "Surface") {
            roma = data;
        }
        # 日本語の場合
        if (XMLENDELEM == "Roman") {
            yomi = data;
        }
        if (XMLENDELEM == "Word") {
            if (yomi == "" && roma != "") {
                yomi = roma;
            }
            espeak_argv = espeak_argv " " yomi;
            roma = yomi = "";
        }
    }
    close(tmp_file);

    # テンポラリファイルの削除
    system("rm -f " tmp_file);

    # espeak で喋らせる
    espeak_exec = espeak_cmd " " espeak_opt "'" espeak_argv "'";
    system(espeak_exec);
}

xgawk では xml プラグマを読み込むことで XML が扱えるようになるのですが、最初に XMLMODE を 0 にしてセットする必要があります。

The use of the line ”@load xml” sets XMLMODE to -1 as a side-effect. The use
of the command line option ”-l xml' does the same. So, most users prefer the
latter methods instead of setting XMLMODE directly.

つまり、XMLMODE はデフォルトでは -1 に設定されているため、必要に応じて変更の必要があります。

実行方法はAWK Users JP :: awk で喋らせてみると同じです。

$ xgawk -f say_japanese.awk 'あなたは English しゃべれますか'

意外に、XMLMODE を使った例がAWK Users JP :: AWK ならどう書く? になかったので今回 xgawk を使った XML のパースにチャレンジしてみました。

tag_xgawk.png