Windows Scripting Host 5

vs. Perl

今まで見てきたようにWindows Scripting Hostはある程度Perlの代わりとして 使うことができます。ここではPerlの代わりになるかをもう少し見ていきます。

連想配列

Perlでよく使う連想配列に相当する機能は Dictionaryオブジェクトを用いることによって実現できます。 連想配列とは簡単にいうと、配列の添え字に文字列を使えるようにしたようなものです。
最初にDictionaryオブジェクトを作成します。
    var dicobj = WScript.CreateObject(
                        "Scripting.Dictionary");
次のようにキーと値を関連付けます。
    dicobj.Add(key, value);
キーから値を取り出すには次のようにします。
    a = dicobj.Item(key);
具体例は次です。例えば次のような得点表があったとします。
scripts/score.csv
-------------------------------------------
名前,性,国語:Int,算数:Int,理科:Int,社会:Int
さくら,女,75,71,8,66
知世,女,62,2,89,60
小狼,男,51,28,70,31
千春,女,68,61,46,12
奈緒子,女,89,55,69,24
利佳,女,79,30,79,81
ここから各人の国語の点数だけをメモリ上に格納し、 その中からさくらちゃんの国語の点数を表示します。
scripts/dictionary1.js
----------------------------------------------
var str, arr;
var fs = WScript.CreateObject(
                "Scripting.FileSystemObject");
var stream = fs.OpenTextFile("score.csv");
var dicJpn = WScript.CreateObject(
                "Scripting.Dictionary");

stream.SkipLine();
while(!stream.AtEndOfStream) {
    str = stream.ReadLine();
    arr = str.split(",");
    //arr[0]が名前、arr[2]が国語の点数
    dicJpn.Add(arr[0], arr[2]);
}
stream.Close();

//さくらちゃんの国語の点数を表示
WScript.Echo(dicJpn.Item("さくら"));
最後は次のようにしてもOKです。
WScript.Echo(dicJpn("さくら"));
詳しくはこちら

正規表現

Perlに限らずテキスト処理でよく使われるのが正規表現ですが、 JavaScriptでは次のように使います。
    /pattern/.test(string)
string がパターンにマッチングすればtrueがそうでなければfalseが返ります。 次は、上の得点表で名前が「さ」で始まり「ら」で終わる人の得点を表示する スクリプトです。
scripts/regex.js
--------------------------------------------------
var str, arr;
var fs = WScript.CreateObject(
                    "Scripting.FileSystemObject");
var stream = fs.OpenTextFile("score.csv");

stream.SkipLine();
while(!stream.AtEndOfStream)
    if(/^さ.*ら,/.test(str = stream.ReadLine())) {
        arr = str.split(",");
        WScript.Echo(arr[0] + " " + arr[2]);
    }
stream.Close();
詳しくはこちら

フォーマット

計算屋にとって痛いのは書式付きで数値を文字列に変換できないことです。 そこで4種類の関数を作ってみました。
関数説明Cでの書式
FormatS(num, width)10進整数 FormatS(123, 4) → _123%4d
FormatZ(num, width)10進整数0付き FormatZ(123, 4) → 0123%04d
FormatF(num, width, prec)小数 FormatF(0.12, 6, 3) → _0.120%6.3f
FormatE(num, width, prec)指数 FormatE(0.12, 9, 2) → _1.20e-01%9.2e
_はスペースの代わりです。
フォーマットを選んで、numに数値、width・precisionのそれぞれに自然数を入れて ボタンを押してください。選ばれたフォーマットで数値が表示されます。
FormatS
FormatZ
FormatF
FormatE
num
width
precision
私自身あまり動作確認していないので不具合があればご一報ください。
function test1(form) {
    var str;
    var fnum = num.value - 0;
    var iwidth = parseInt(width.value);
    var iprecision = parseInt(width.value);
    with(form) {
        if(format_type[0].checked)
            str = FormatS(fnum, iwidth);
        else if(format_type[1].checked)
            str = FormatZ(fnum, iwidth);
        else if(format_type[2].checked)
            str = FormatF(fnum, iwidth, iprecision);
        else if(format_type[3].checked)
            str = FormatE(fnum, iwidth, iprecision);
        alert(num.value + " : " + str);
    }
}

function FormatS(num, width) {
    var pos;
    var str = num + "";
    if(str.indexOf("e") != -1) {    //指数表示されればエラー
        WScript.Echo(str + " : 不適切な数値です(FormatS)");
        WScript.Quit();
    }
    if((pos = str.indexOf(".")) != -1)  //小数点以下切り捨て
        str = str.substring(0, pos);
    
    for(; str.length < width; str = " " + str)
        ;
    return str;
}

function FormatZ(num, width) {
    var pos;
    var str = num + "";
    if(str.indexOf("e") != -1) {
        WScript.Echo(str + " : 不適切な数値です(FormatZ)");
        WScript.Quit();
    }
    if((pos = str.indexOf(".")) != -1)
        str = str.substring(0, pos);
    
    for(; str.length < width; str = "0" + str)
        ;
    if((pos = str.indexOf("-")) != -1)
        str = "-" + str.substring(0, pos)
                + str.substring(pos + 1, str.length);
    return str;
}

function FormatF(num, width, prec) {
    var exp, pos, i;
    var str = num + "";
    
    //小数形式(xxx.xxx)にする
    if((pos = str.indexOf("e")) != -1) {        //指数
        exp = parseInt(str.substring(pos + 1, str.length));
        str = str.substring(0, pos);
        if(exp != 0)
            str = MovePoint(str, exp);    //小数点を移動
    }
    else if(str.indexOf(".") == -1)             //整数
        str += ".0";
    
    pos = str.indexOf(".");
    var cprec = str.length - pos - 1;       //現在の精度
    if(cprec > prec)            //精度がよすぎればカット
        str = str.substring(0, pos + prec + 1);
    else                        //悪ければ0を付け足し
        for(i = cprec; i < prec; i++)
            str += "0";
    for(; str.length < width; str = " " + str)
        ;
    
    return str;
}

function FormatE(num, width, prec) {
    var exp, pos, dexp;
    
    var str = num + "";
    
    //仮数と指数を特定する
    exp = 0;
    if((pos = str.indexOf("e")) != -1) {        //指数
        exp = parseInt(str.substring(pos + 1, str.length));
        str = str.substring(0, pos);
        pos = str.indexOf(".");
    }
    else if((pos = str.indexOf(".")) == -1)     //整数
        str += ".0";
    
    if((dexp = (str.charAt(0) == "-" ? 2 : 1) - pos) == 0)
        if(str.charAt(0) == "0") {          //0.xxxのとき
            for(dexp = 1; str.charAt(dexp + 1) == "0"; )
                dexp++;
            str = str.charAt(dexp + 1) + "."
                    + str.substring(dexp + 2, str.length);
            exp = -dexp;
            dexp = 0;
        }
    
    exp -= dexp;
    if(dexp != 0)
        str = MovePoint(str, dexp);   //小数点を移動
    
    //指数部
    exp = FormatZ(exp, 3);
    if(exp.charAt(0) == "0")
        exp = "+" + exp.substring(1, exp.length);
    else if(exp.charAt(0) != "-")
        exp = "+" + exp;
    
    //仮数部
    str = FormatF(str, width - exp.length - 1, prec);
    
    return str + "e" + exp;
}

function MovePoint(str, order) {
    var space;
    
    //小数点が移動できるように前後に0を付け足す
    var pos = str.indexOf(".");
    if(order > 0) {
        space = str.length - pos - 2;       //移動できる余地
        for(; space < order; space++)
            str += "0";
    }
    else {
        space = pos - (str.charAt(0) == "-" ? 2 : 1);
        pos += -order - space;
        for(; space < -order; space++)
            str = "0" + str;
    }
    
    //小数点を動かす
    str = str.substring(0, pos)         //小数点を一旦なくす
                + str.substring(pos + 1, str.length);
    pos += order;                       //小数点の新しい位置
    return str.substring(0, pos) + "."
                + str.substring(pos, str.length);
}

first, prev, next, noframe, exit
Written 6/27/98