前回のエントリの補足です。
前回はWrite-Host
とWrite-Output
の違いについて触れ、全くの別物であることを説明しました。
別物であるとはいえ、実際の利用においては両方ともコンソールに文字列を表示する用途で同様に扱うことが多いと思います。
そこで本エントリではコンソールに文字列を表示する場合の両者の違いについて説明していきます。
Write-Host、Write-Outputの入力パラメータについて
本題に入る前に、Write-Host
とWrite-Output
の入力パラメータについて軽く触れます。
Write-Host
の-Object
、Write-Output
の-InputObject
は名前付き引数にも関わらず複数の入力を受け付けることができ可変長引数の様に振る舞います。
# Write-Hostの入力パラメータ -Object が3つの引数を受け取り可変長の様に振る舞っている PS C:\> Write-Host 123 456 789 123 456 789 # Write-Outputの -InputObject パラメーターも同様 PS C:\> Write-Output 123 456 789 123 456 789
一見不可解な動作ですが、これはWrite-Host
の-Object
、Write-Output
の-InputObject
パラメータにValueFromRemainingArguments
属性が設定されているためです。
ValueFromRemainingArguments
属性についてはabout_Functions_Advanced_Parametersに詳細が記載されており、
ValueFromRemainingArguments 引数は、パラメーターが、関数の他のパラメーターに割り当てられていないコマンド内のすべてのパラメーター値を受け取ることを示します。
との説明がなされています。
これは、例えば3つのパラメーターを持つ関数を5つの引数で呼び出した場合2つの引数が余りますが、ValueFromRemainingArguments
属性が付いているパラメーターにこの余りをまとめてリストとして渡されます。
言葉で説明するより以下の例を見た方がわかりやすいと思います。
ValueFromRemainingArguments
属性が付いた-Input2
を持ち、3つの引数をとる簡単なファンクションFunc1
を定義します。
function Func1 { [CmdletBinding()] param ( $Input1, [Parameter(ValueFromRemainingArguments=$true)] $Input2, $Input3 ) Write-Host "-Input1 = $Input1(Type=$($Input1.GetType()))." Write-Host "-Input2 = $Input2(Type=$($Input2.GetType()))." Write-Host "-Input3 = $Input3(Type=$($Input3.GetType()))." }
このFunc1
に対して3つ以上の引数を指定すると以下の様になり、-Input2
に余りの引数がリストの形でまとめられているのがわかります。
この例の様にパラメーター名を指定しない場合は後ろの引数がまとめられます。
(-Input2
は2 4 5
でなく3 4 5
なのに注意してください。)
PS C:\> Func1 1 2 3 4 5 -Input1 = 1(Type=int). -Input2 = 3 4 5(Type=System.Collections.Generic.List[System.Object]). -Input3 = 2(Type=int).
パラメーター名を指定した場合は以下の様になります。
# パラメータ名で割り当てられなかった余りがValueFromRemainingArgumentsを持つパラメータにまとめられる PS C:\> Func1 1 -Input3 2 -Input1 3 4 5 -Input1 = 3(Type=int). -Input2 = 1 4 5(Type=System.Collections.Generic.List[System.Object]). -Input3 = 2(Type=int). # ValueFromRemainingArgumentsを持つパラメータを名前付きで指定するとパラメータの数が合わずエラーとなる PS C:\> Func1 1 -Input2 2 3 4 5 Func1 : 引数 '4' を受け入れる位置指定パラメーターが見つかりません。 発生場所 行:1 文字:1 + Func1 1 -Input2 2 3 4 5 + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Func1]、ParameterBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,Func1
Write-HostとWrite-Outputの表示の違い
ここから本題に入りWrite-Host
とWrite-Output
の表示の違いを説明します。
色指定の有無
まずは基本から。
Write-Host
では-ForegroundColor
により文字の前景色、-BackgroundColor
により背景色を指定することができます。
前回のエントリで説明したとおり、Write-Output
は出力ストリームにオブジェクトを出力するためのものですので色を付けることはできません。
改行の有無
Write-Host
では-NoNewline
により文字列表示後に改行をつけるか否かを設定できます。
-NoNewline
はSwitchパラメーターで既定値は$true
です。
Write-Output
にはこのパラメータは無く、常に改行付きの文字列がコンソールに表示されます。
オブジェクトの種類による違い
入力に文字列以外のオブジェクトを指定した場合、Write-Host
では入力オブジェクトを無条件にToString()
した結果が表示されます。
Write-Output
ではPowerShellの書式設定に応じた表示となります。
こちらも前回説明した通り、Write-Output
したオブジェクトは最終的にFormat-*(Format-Default)
が呼ばれて書式設定されるためになります。
可変長引数を受けた場合の表示の違い
最初に説明したとおり、Write-Host
とWrite-Output
では可変長の引数を受けることができます。
Write-Host
では入力値を横並びに表示します。
-Separator
パラメーターで横並びにする際の区切り文字を指定することもできます。
Write-Output
では入力値を配列にして返します。このため最終的なコンソールへの表示は縦並びとなります。
配列を指定した場合の違い
引数に配列を指定した場合は可変長引数を受けた場合と同様の結果となります。
ハッシュテーブルを指定した場合の違い
引数にハッシュテーブルを指定した場合、Write-Host
はオブジェクトの配列を受けた扱いとなり"System.Collections.DictionaryEntry"の文字列が横並びで表示されます。
Write-Output
ではキーと値の内容が表示されます。
補足
一番利用頻度が高いであろう文字列の出力についての詳細はぎたぱそ先生の以下のエントリが非常に有用ですので参考にしてください。