読者です 読者をやめる 読者になる 読者になる

Monadで激昂

Monad .NET とオブジェクト

ネットサーヒンしてたら Windows の次期シェル Monad さんに出会った。

これがとっても面白い!。わははは。使ってみるとぽか〜んとして大爆笑です。すごいです。ただのシェルじゃなくてこれはもう .NET Framework へのコマンドラインインタフェースです。

普通のシェルとの違いでわかりやすいところといえば、この Monad (MSH)、標準入出力が文字列ベースじゃなくて .NET のオブジェクトだ!。ということ。つまり、

MSH D:\> get-childitem


    Directory: Microsoft.Management.Automation.Core\FileSystem::D:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/01/30     16:18       1691 altchecker.js
-a---        2005/04/14     23:53      33792 nyoro.doc
-a---        2004/03/11      1:25         39 test.css
d----        2005/01/14      0:44            cygwin
d----        2003/08/23      1:26            downloads
d----        2004/03/27     20:47            DRIVERS
d----        2006/02/04      3:04            games
d----        2004/02/01     13:18            home
d-r--        2006/02/04     16:38            mydocuments
d----        2005/02/25     19:53            pythontools

要するに ls コマンドみたいな get-childitem というのがあるんですけど、このコマンドの戻り値って全然文字列じゃなくて、.NET の System.IO.FileInfo 型のオブジェクト、の配列!。なんだこのシェル。

MSH D:\> $a = get-childitem
MSH D:\> $a -is [array]
True
MSH D:\> $a[0]


    Directory: Microsoft.Management.Automation.Core\FileSystem::D:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/01/30     16:18       1691 altchecker.js


MSH D:\> $a[0].Length
1691

これで分かりますでしょうか。get-childitem の戻り値を $a に代入して、型は array で、インデックス0番にアクセスすると一つめのファイルの情報が帰ってきて、$a[0].Length プロパティにアクセスすると容量が返ってくる。.NET クラスライブラリの FileInfo メンバ にあるもの全部ここで使えちゃいます。わはは。何これ。

Monad と型変換

型変換もすごい。

MSH D:\> $a = [xml]"kaisugi"
MSH D:\> $a.oogatta.jitensya
kaisugi

文字列型の頭に [xml] くっつけて、xml 型にキャストして $a に代入。びっくり。もっとびっくりするのが、この角括弧を使った型キャストの中身、.NET のクラスなんでもいけちゃうみたいな…。

MSH D:\> get-item altchecker.js


    Directory: Microsoft.Management.Automation.Core\FileSystem::D:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/01/30     16:18       1691 altchecker.js

get-item というコマンドは、文字列の引数を受け取ってさっき出てきた FileInfo のオブジェクトを返します。これは普通のやり方。で、型キャストを強引に使うと…、

MSH D:\> [System.IO.FileInfo]"d:\altchecker.js"

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/01/30     16:18       1691 altchecker.js

このように…。表示がちがうので、どうやら標準のコマンドを使うと出力に関してシェルが便宜を図ってくれるようですが、中身は一緒です、多分…。

MSH D:\> $a = get-item altchecker.js
MSH D:\> $a -is [System.IO.FileInfo]
True
MSH D:\> $b = [System.IO.FileInfo]"d:\altchecker.js"
MSH D:\> $b -is [System.IO.FileInfo]
True

シェル?インタプリタ

ところでこのシェル、普通に地べたに

MSH D:\> 2+2
4

とかできるのでほとんどスクリプト言語コマンドラインインタプリタ状態ですが(Expression mode)、もちろんちゃんと入力をコマンドとして解釈するコマンドシェルの機能もあって(Command mode)、その辺は次のルールで自動認識するとのこと。

2+2Expression mode - 数字で始まる
"foobar"Expression mode - クォートで始まる
foobarCommand mode - 文字列で始まる
& "foobar"Command mode - アンパサンドで始まる
. "my script.msh"Command mode - ドットと空白の二文字で始まる(これは、現在のスコープでシェルスクリプトを実行する、との意味)
.125Expression mode - ドットの次に、空白や文字列ではなく数字が続く
.foobarCommand mode - この場合ドットは".foobar"というコマンド名の一部

しかも、() 括弧を使うことでこの自動認識を再実行できるとのこと、すなわち…、

Write-Host (2+2)2+2は式として評価して、write-host "コマンド" の実行に対する引数として渡される
2 + (Get-Date).day2 から始まるので式なんだけど、括弧でリセットして Get-Date はコマンドとして扱ってもらい、実行結果を式の一部として評価する

わははっは。笑っちゃいます。上の xml の例と合わせてみると、

MSH D:\> get-content test.xml
kaisugi
MSH D:\> $a = [xml](get-content test.xml)
MSH D:\> $a.oogatta.jitensya
kaisugi

どどーん。

お作法

こんなハチャメチャな Monad さんですが、基本の作法はだいたいお馴染みのシェルと同様。パイプに、リダイレクトです。まだまだβ版で、ファイルからコマンドへのリダイレクトが出来なかったりするんですが、

MSH D:\> *-item[TAB]
MSH D:\> clear-item[TAB]
MSH D:\> copy-item[TAB]
MSH D:\> get-item
…

的なコマンド名補完もできたり、この「動詞-名詞」と決まっているらしい長ったらしいコマンドも alias 付けられるし(ls って打ったら get-childitem が実行された…)、かなり楽しみです!。

.NET Framework 2.0 があれば動き、わかりやすいドキュメント一式もあるので、Windows ネットワークの管理者だけでなく Windows シェル好きのみなさんは是非ダウンロードです!。

やりたい放題

MSH D:\> $reg = [regex]"u[nm]ko"
MSH D:\> "unko" -match $reg
True
MSH D:\> $reg.match("unko").length
4
MSH D:\> $reg.match("unko").success
True
MSH D:\> $reg.match("unko").index
0

とかもうやりたい放題です。もちろん実用するときには…、

MSH D:\> get-childitem | where-object {$_.name -match "\.js$"}


    Directory: Microsoft.Management.Automation.Core\FileSystem::D:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/01/30     16:18       1691 altchecker.js

こんなふうに使えます。パイプで文字列ではなく FileInfo が渡ってきてるのがよくわかります。いやはや。楽しみです。

ダウンロード

上から、.NET Framework 2.0、MonadMonadのドキュメント。ドキュメントは「チートシート」的な一覧表まで入っていてなんだか気が利いています。