コマンドプロンプトから色々な処理系でワンライナー:2012年バージョン

id:eel3:20090321:1237633275 から3年。手元のPCに何故か入っている言語処理系の数が増えた結果、コマンドプロンプトからワンライナーできる処理系増えた。これはもうワンライナーするしかないだろう。

いやあ、頑張ればF#も(厳密にはワンライナーじゃない気がするけど)何とかなるのね……。

ActivePerl 5.14.2.1402 MSWin32-x86-multi-thread

相変わらずインストールしてあるけど使い方が分からないPerl*1。かじってみたけと、肌にあわないんだよなあ。何でだろう?

D:\temp>perl -e "print 3 * 2"
6
D:\temp>perl -e "for ($i = 0; $i < 3; ++$i) { print \"$i\n\" }"
0
1
2

D:\temp>perl -e "foreach $i (0..2) { print \"$i\n\" }"
0
1
2

D:\temp>

Windows版『ミニマルPerl』的なアプローチがあれば、また違ってくるのかもしれない。

CoffeeScript 1.2.0

新台入荷。つい最近入れたばかりで全く触っていない。

D:\temp>coffee -e "console.log 3 * 2"
6

D:\temp>coffee -e "console.log i for i in [0, 1, 2,]"
0
1
2

D:\temp>coffee -e "console.log i for i in [0..2]"
0
1
2

D:\temp>coffee -e "[0..2].forEach (i) -> console.log i"
0
1
2

D:\temp>

CoffeeScriptの処理系自体はJavaScriptへのトランスレータでしかない。で、処理系がNode.js前提なJavaScriptで書かれているので、実行する際にNode.jsが必要。

多分というか十中八九、CoffeeScriptのREPLや -e によるワンライナーではトランスレータが吐き出したJavaScriptのコードをNode.jsで実行しているのだろう。なのでNode.jsで使える機能を使っても問題ない反面、その機能の素性(Node.js固有なのか、ECMA-262の機能なのか、第3版なのか第5版なのか等々)を踏まえておかないと何時か痛い目に遭う気がする。

GNU Awk 3.1.7

時々BEGINパターンと間違えてENDパターンでワンライナーしようとして、動かなくて悩むことがある :)

D:\temp>gawk "BEGIN { print 3 * 2 }"
6

D:\temp>gawk "BEGIN { for (i = 0; i < 3; ++i) print i }"
0
1
2

D:\temp>

まあしかし、基本的にawkは「テキストレコードのフィルタ」要員なのよね、私の中では。

GNU CLISP 2.41

足し算する時に`+'を1回しか書かなくて済むので、何かを大量に買い込む前に必要な金額を計算する時に重宝している。そんなのは私だけ?

D:\temp>clisp -q -x "(* 3 2)"
6

D:\temp>clisp -q -x "(loop for i in '(0 1 2) do (print i))"

0
1
2
NIL

D:\temp>

ワンライナーで計算機代わりに使う分には、何もしなくても評価結果が出力される挙動は気に入っているのだけど……場合によっては評価結果が出力されない方が望ましい場合もある。出力しない方法ってあるのかなあ?

GNU bash 3.1.17(1)-release

未だにshやbashを-cオプション付きで実行する具体的なシチュエーションが思い浮かばない。

D:\temp>bash -c "expr 2 + 3"
5

D:\temp>bash -c "for i in 0 1 2; do echo $i; done"
0
1
2

D:\temp>

まあ普通はbashを立ち上げて対話的に操作するか、シェルスクリプトで操作するものだと思う。

Gauche 0.9.2 utf-8 i686-pc-mingw32

最後に「-e "(exit)"」や「-E exit」と付けるのが面倒なので、ワンライナーではあまり使わない。使いたい時はREPLか、スクリプトを書くことが多い。

D:\temp>gosh -e "(print (* 3 2))" -e "(exit)"
6

D:\temp>gosh -E "print (* 3 2)" -E exit
6

D:\temp>gosh -u srfi-1 -e "(for-each print (iota 3))" -e "(exit)"
0
1
2

D:\temp>

printとか使わないと評価結果が見れない所も面倒で、最近はワンライナーする時はCLISPを使っている。この辺は用途次第で、単に私がLispの処理系でワンライナーする9割以上が計算機代わりな為にCLISPの方が都合がよいだけだ。

JavaScript-C 1.7.0 2007-10-03 (SpiderMonkey)

ビルドするのが面倒なので、古いバージョンのまま。

D:\temp>js -e "print(3 * 2)"
6

D:\temp>js -e "for (i = 0; i < 3; ++i) print(i)"
0
1
2

D:\temp>js -e "for (i in new Array(0, 0, 0)) print(i)"
0
1
2

D:\temp>js -e "for (i in [0, 0, 0]) print(i)"
0
1
2

D:\temp>

そろそろ別の、自前でビルドしなくても誰かがバイナリを公開してくれている処理系を探そうかな。

Lua 5.2.0

Wiresharkプラグインで弄くることはあるけど、スタンドアローンLuaを使う機会は無いなあ。

D:\temp>lua52 -e "print(3 * 2)"
6

D:\temp>lua52 -e "for i = 0, 2 do print(i) end"
0
1
2

D:\temp>lua52 -e "for i, v in ipairs({0, 1, 2}) do print(v) end"
0
1
2

D:\temp>lua52 -e "function count (i, max) if i <= max then print(i) return count(i+1, max) end end; count(0, 2)"
0
1
2

D:\temp>

しかしよく考えたら、手元の中では数少ない「末尾呼び出しを最適化をしてくれて且つインタプリタ的に使用できる」処理系の1つなんだよな。

Microsoft F# 2.0 Interactive ビルド 4.0.30319.1

厳密にはワンライナーではないけど、Reginaと同じ方法で強引に。

D:\temp>echo printfn "%d" (3 * 2);; #quit;; | fsi.exe --nologo --quiet
6

D:\temp>echo for i = 0 to 2 do printfn "%d" i;; #quit;; | fsi.exe --nologo --quiet
0
1
2

D:\temp>echo for i in [ 0 .. 2 ] do printfn "%d" i;; #quit;; | fsi.exe --nologo --quiet
0
1
2

D:\temp>

今の所、ワンライナー用の正規のオプションは存在しない模様。えっ、素直にF#インタラクティブのREPLを使えって?

Microsoft Windows PowerShell 2.0

PowerShellのこのオプションを使う人はどの程度存在するのだろう? PowerShell使いは最初からPowerShellのシェルを使ってる気がする。

D:\temp>powershell -Command 3 * 2
6

D:\temp>powershell -Command for ($i = 0; $i -lt 3; $i++) {$i}
0
1
2

D:\temp>powershell -Command foreach ($i in 0..2) {$i}
0
1
2

D:\temp>powershell -Command "0..2 | %{$_}"
0
1
2

D:\temp>powershell -Command 0..2
0
1
2

D:\temp>

私はコマンドプロンプト上に構築した環境を手放せないので、コマンドプロンプト上で一時的にPowerShellを使うことが圧倒的に多いのだけど。

Microsoft Windows Script Host 5.7

まあ普通はWSHワンライナーだなんて考えないものだけど、やりようはあるもので。

id:eel3:20120227:1330345751 のスクリプトを使ってJScriptワンライナー

D:\temp>cscript jscript_oneliner.js "WScript.Echo(3 * 2)"
6

D:\temp>cscript jscript_oneliner.js "for (i = 0; i < 3; ++i) WScript.Echo(i)"
0
1
2

D:\temp>cscript jscript_oneliner.js "for (i in new Array(0, 0, 0)) WScript.Echo(i)"
0
1
2

D:\temp>cscript jscript_oneliner.js "for (i in [0, 0, 0]) WScript.Echo(i)"
0
1
2

D:\temp>

そして id:eel3:20120227:1330346040 のスクリプトVBScriptワンライナー

D:\temp>cscript vbscript_oneliner.vbs "WScript.Echo 3 * 2"
6

D:\temp>cscript vbscript_oneliner.vbs "For i = 0 To 2 : WScript.Echo i : Next"
0
1
2

D:\temp>cscript vbscript_oneliner.vbs "For Each i In Array(0, 1, 2) : WScript.Echo i : Next"
0
1
2

D:\temp>

VBScriptワンライナーだなんて需要なさそうだなあ。

Node.js 0.6.11

SpiderMonkeyからの代替品候補その1。

SpiderMonkeyRhinoではprint()という関数が用意されているけど、Node.jsではクライアントサイドJavaScriptでお馴染みのconsole.logと同じ名前の関数で標準出力に書き出すみたい。

D:\temp>node -e "console.log(3 * 2)"
6

D:\temp>node -e "for (i = 0; i < 3; ++i) console.log(i)"
0
1
2

D:\temp>node -e "for (i in new Array(0, 0, 0)) console.log(i)"
0
1
2

D:\temp>node -e "for (i in [0, 0, 0]) console.log(i)"
0
1
2

D:\temp>

Windows用の実行ファイルも提供されているし、ライブラリを見ると色々と面白そうな機能ももっている。サーバサイドJavaScriptが流行るか否かはともかく、JavaScriptPerlRubyみたいにちょっとしたツールを書く為の処理系としてメジャーになってくれることを期待したいなあ。

PhantomJS 1.4.1

SpiderMonkeyからの代替品候補その2……ではない。残念。

今の所ワンライナー用のオプションは無いので、id:eel3:20120227:1330277669 のスクリプトを使ってワンライナー

D:\temp>phantomjs phantomjs_oneliner.js "console.log(3 * 2)"
6

D:\temp>phantomjs phantomjs_oneliner.js "for (var i = 0; i < 3; ++i) console.log(i)"
0
1
2

D:\temp>phantomjs phantomjs_oneliner.js "for (var i in new Array(0, 0, 0)) console.log(i)"
0
1
2

D:\temp>phantomjs phantomjs_oneliner.js "for (var i in [0, 0, 0]) console.log(i)"
0
1
2

D:\temp>

無理やり感が漂うけど、ワンライナーワンライナー。まあNode.jsとかRhinoとか使えば済む話だけど。PhantomJSの本分は別のところにある気がするんだよなあ。

REXX-Regina_3.5

厳密にはワンライナーではないけど、無理やり。

D:\temp>echo say 3 * 2 | regina
6

D:\temp>echo do i = 0 to 2; say i; end | regina
0
1
2

D:\temp>

F#インタラクティブと異なりReginaはREPLではないので、こんな使い方をしても異論は出ないだろう……そもそもREXXを選択する時点で素直じゃないって?

Rhino 1.7 R3

SpiderMonkeyからの代替品候補その2。

簡単に実行できるように、こんなバッチファイルを用意。

@echo off
setlocal

set CLASSPATH=-classpath "%~dp0js.jar;."
java %CLASSPATH% org.mozilla.javascript.tools.shell.Main %*

endlocal
D:\temp>rhino -e "print(3 * 2)"
6

D:\temp>rhino -e "for (i = 0; i < 3; ++i) print(i)"
0
1
2

D:\temp>rhino -e "for (i in new Array(0, 0, 0)) print(i)"
0
1
2

D:\temp>rhino -e "for (i in [0, 0, 0]) print(i)"
0
1
2

D:\temp>

Javaで実装されてるので、JREさえ入っていればOSの違いを気にせず簡単に持ち運び可能なのはメリットかもしれない。しかしJREを入れて且つしっかりアップデートしていく必要があるのは面倒だし、LinuxとかではOpenJDKで動いてくれない危険もあるんだよなあ。

あと色々と便利な機能を使うにはJavaAPI頼りになってしまうのが面倒。

RubyInstaller 1.9.3p0

そういえば最近Rubyワンライナーしてない。irbばかり使っている気がする。

D:\temp>ruby -e "p 3 * 2"
6

D:\temp>ruby -e "3.times {|i| p i }"
0
1
2

D:\temp>ruby -e "0.upto(2) {|i| p i }"
0
1
2

D:\temp>ruby -e "(0..2).each {|i| p i }"
0
1
2

D:\temp>ruby -e "for i in 0..2; p i; end"
0
1
2

D:\temp>echo hoo:bar:baz: | ruby -072 -n -e "p $_ if !/\n/"
"hoo:"
"bar:"
"baz:"

D:\temp>

SCM 5e7

すっかり存在を忘れていた……。

D:\temp>scm -e "(print (* 3 2))"
6

D:\temp>scm -c "(print (* 3 2))"
6

D:\temp>scm -r srfi-1 -e "(for-each print (iota 3))"
0
1
2

D:\temp>

これまたGaucheと同じく、printとか使わないと評価結果が見れない所が面倒なので使わない。Schemeの処理系としても大抵はGaucheを使うし……。

Tcl/Tk 8.4 tclsh

tclshのドキュメントを見てもワンライナー用のオプションはなさそうだけど、これまたF#やReginaと同様に無理やり……。

D:\temp>echo puts [expr 3 * 2] | tclsh84
6

D:\temp>echo foreach {i} {0 1 2} {puts $i} | tclsh84
0
1
2

D:\temp>

もっともtclshはインタラクティブに使えるので無理やりコマンドプロンプトからワンライナーする必要性は薄い気がする。

tcsh-6.13.00 for Win32 7.09

bashに移行したこともあり、ぜんぜん使っていないなあ。

D:\temp>tcsh -c "expr 2 + 3"
5

D:\temp>tcsh -c "echo foo bar baz"
foo bar baz

D:\temp>

*1:一部ツールがPerlで書いてあるので必要だけど、そのツールを書いたのは私ではないので……