言わずと知れたホストに出力するコマンドレット。
簡単に使えて、何の変哲もないといえば無いのだが、実はなんとなく良く分からないコマンド。
コンソールに色つきで出力したい、なんて時はこのコマンドの出番なのだが意外と色々戸惑うことも有ったので少し纏めておく。
PS>Write-Host A |
いままで特に不思議に思わず普通に使ってきたのだが、2つめのコマンドはなぜこんな結果になるのだろう。
通常、「コマンドレット A B」という形式は位置パラメータの1番目に”A” 、2番目に”B”と解釈されるものと思う。
なので、位置パレメータを1つしか持たない「Write-Host」はエラーになるのが普通ではなかろうか。
実際、「Write-Warning」でためしてみると、予想通りのエラーになる。
パラメータの型が<Object>で位置パラメータが1つ、と言ったあたりに何か理由があるのかとも思って調べてみたが結局良く判らなかった。
Trace-Commandで見てみると、パラメータがArrayListとして解釈されているっぽい感じではあるが、それがなぜかまでは判らない。
すべてのコマンドを検証したわけではないが、このような動作をするのは他に「Read-Host」くらいしか見つけられなかった。
とりあえず現時点ではそういうものだと思うことにしよう。(^^;
次に、連想配列を「Write-Host」に渡した時の動作を見てみる。
PS>$array = @{a=1;b=2;c=3} Name Value
|
そのまま出力すれば内容が表示されるのだが、こいつに色を指定しましょうなどと思って「Write-Host」を使うと残念な結果になる。
まずはこの時、「Write-Host」がどのような動作をしているのかを確認してみる。
「DictionaryEntry」が3つ出力されているので中身をループしながらToStringって感じだろうか。
PS>$array.GetEnumerator() | %{$_.ToString()} |
内容的には合っているが表示形式がちょっと違う。
こうか。
PS>$array.GetEnumerator() -join " " |
実際にはこんな感じの条件がついているのかな。
PS>if($array -is [System.collections.IEnumerable]) {$array.GetEnumerator() -join " "} |
さて、実はここからが本題で、これまでの話とはそれほど関係ないのだが、以下の記事でハッシュテーブルに色をつけて表示するにはどうすればよいかという話が有った。
Using Write-Host to display a hashtable
全体に色をつければ良いようなのでOut-Stringして結果をWrite-Hostするだけの事なのだが通常は特定の行に色を付けたいよなと思って考え始めたところWrite-Hostの仕様がいまひとつ判らなかったという事で前段の調査になった。
以前似たようなことをやった事があるPowerShell: ◆特定のプロセスに色をつけて表示するのだが、若干うまく行かないケースがあるので少しだけ違った方法でやってみた。
今回も今ひとつスマートな方法は思いつかず、以下のような若干ベタな感じ。
001 002 003 004 005 006 007 008 | $array = @{a=1;b=2;c=3} $array.GetEnumerator() | %{ Write-host "key`tvalue`r---`t-----" }{ $para = @{} if($_.key -eq "b"){$para.Add("foreground","red")} Write-Host $_.key `t $_.value @para } |
やっぱり素直にOut-Stringでやったほうが良さそうかな。
001 002 003 004 005 006 | $array = @{a=1;b=2;c=3} $array | Out-String -Stream | %{ $para = @{} if($_ -match '^b\b'){$para.Add("foreground","red")} Write-Host $_ @para } |
本当はToStringをオーバーライドしたりするとスマートかなと思って書き始めたのだが、そちらはうまく行かなかった。
あまり深く考えたことはなかったのですが、たしかにWrite-Hostの挙動は珍しいですね。
返信削除おそらくですが、コマンドレット内部では-objectパラメータの値(WriteHostCommand.Object)を見るのと同時に、$argsに相当する値(WriteHostCommand.MyInvocation.UnboundArguments)も見ているんだと思います。
複数の名前なしパラメータが渡されると、パラメータセットが解決できないのでUnboundArgumentsに値が渡ることになると思います。
おそらくそういう動作になるように、-object以外のパラメータが位置=namedで必須=falseになってるんでしょう。
(二つ以上の名前なしパラメータを渡すと自動的に、パラメータセットが解決できない状態になるようにしている)
ハッシュテーブルの色変更ですが、hashtableクラスに対応するformat.ps1xmlのスクリプトを書いてUpdate-FormatData(上書き)するのがPowerShell的なアプローチになるのかなと思いました。
正月に休暇をとっていたので気づくのが遅くなりました。
返信削除年末までご苦労様です。
ハッシュテーブルの色変更については私もなんとなくすっきりしないのでご指摘の案も含めて検討してみたいと思います。
今年もよろしくお願いいたします。