Rhinoで自作スクリプトを動かす

WindowsにはJScriptがあるけど、Macには標準ではJavaScriptバッチ処理を書ける仕組みは無い。でも、以前書いたMacでJavaScriptシェル - 今日覚えたことで導入したRhinoを使えばやれるっぽい。

// test.js
var a = parseInt(arguments[0], 10);
var b = parseInt(arguments[1], 10);
print(a + b);

ターミナルから起動。

$ java -jar js.jar test.js 100 200
300

jばっかりだ。

js.jarに対してまずスクリプトのファイル名を渡す。さらにそれ以降に渡した値はargumentsに入る。

これでJavaScriptバッチ処理とかも書けそうだ。ファイルアクセスはJavaのクラスライブラリを呼び出すんだよねきっと。vimからマクロ風に呼び出したりとかもできるかな。

あと、拡張子jsに「java -jar js.jar」を関連付け設定したいけど、Macでのやりかたわからない。

追記 : 標準入力と標準出力

それから、標準入力と標準出力はおさえておきたい(標準出力はまあprint関数でもいいんだけど)。

まあ結論から言うと、JavaScriptの世界だけでは扱えないっぽい。Javaのクラスライブラリを使えばいける。jjsruby - JSRuby for Rhino (笑) (nakatani @ cybozu labs)が最高に参考になる。

importPackage(java.io);
var stdin = new BufferedReader(new InputStreamReader(java.lang.System['in']));
var stdout = new OutputStreamWriter(java.lang.System.out);

// 標準入力
var line;
var lines = [];
while(line = stdin.readLine()){
    lines.push('' + line);
}

// 標準出力
for(var i = 0; i < lines.length; i++){
    stdout.write(lines[i] + '\n');
    stdout.flush();
}

これは標準入力から取り込んだデータをいったんlinesというstring配列で持って、それをそのまま標準出力に書き出している、無意味なコード。

  • 2行目は、java.lang.System.inと書きたいところだけど、inはJavaScript予約語なのでjava.lang.System['in']と書いてる。JavaScriptではプロパティアクセスとハッシュテーブル要素へのアクセスが同義なので。
  • stdin.readLine()ってやると、JavaのStringのインスタンスが返るので、これをlinesにつめるときに'' + lineってやってJavaScriptの文字列型に変換している。
  • 出力するときは、writeメソッドだけじゃなくstdout.flush()ってやる必要があるっぽい。

一般的なフィルタ系のコマンドは標準入出力を使うので、JavaScriptでそういうのを書きたいならこれが役に立ちそう。vimの外部プログラム呼び出しも、選択範囲と標準入出力とのやりとりのようなので同様。

また追記 : JavaのStringをJavaScriptのstringに変換

上のコードでは'' + lineってやってるけど、String(line)でもいいっぽい。サイ本に書いてあった。