「Write-Host」、「Write-Output」、または「[console] :: WriteLine」の違いは何ですか?


192

メッセージを出力する方法はいくつかあります。経由で何かを出力との間の効果的な違いは何ですかWrite-HostWrite-Outputまたはが[console]::WriteLine

また、私が使用する場合、

write-host "count=" + $count

+出力に含まれます。なんで?式が評価されて、書き出される前に単一の連結された文字列が生成されるべきではありませんか?


4
Write-Output結果を出しているとき。Write-Hostロギング情報を出力しているとき。決して使用しないでください[console]::writeline()
JohnL 2013

2
@JohnLなぜ[console] :: writeline()を使用すべきではないのですか?
David Klempfner、2016年

3
@Backwards_Dave書き込みホストがあるので...わかりました。新しいコンソールウィンドウが表示されたという印象を受けた可能性があります(それはかなり前のことです)。それは起こりませんが、それはpowershellのイディオムではなく、でできないことでできることは何もないという事実が残ってい[console]::writeline("hello world")ますWrite-Host "hello world"。もう1つのより良い、より最近適用可能な答えは、write-hostラップしwrite-informationて、そのデータをストリームに配置して、write-errorキャプチャして他の場所で使用できるようにすることです。[console]::writeline()それはしません
JohnL

回答:


267

Write-Outputパイプラインでデータを送信したいが、必ずしも画面に表示したくない場合に使用します。out-default他に何も最初に使用しない場合、パイプラインは最終的にそれを書き込みます。

Write-Host あなたが反対をしたいときに使用する必要があります。

[console]::WriteLine本質的にWrite-Hostは裏で行われていることです。

このデモコードを実行し、結果を確認します。

function Test-Output {
    Write-Output "Hello World"
}

function Test-Output2 {
    Write-Host "Hello World" -foreground Green
}

function Receive-Output {
    process { Write-Host $_ -foreground Yellow }
}

#Output piped to another function, not displayed in first.
Test-Output | Receive-Output

#Output not piped to 2nd function, only displayed in first.
Test-Output2 | Receive-Output 

#Pipeline sends to Out-Default at the end.
Test-Output 

PowerShellがのパラメーターリストをトークン化する前に連結を処理するWrite-Hostか、文字列補間を使用できるように、連結操作を括弧で囲む必要があります。

write-host ("count=" + $count)
# or
write-host "count=$count"

ところで、パイプラインがどのように機能するかを説明するジェフリー・スノーバーのこのビデオを見てください。PowerShellの学習を始めたとき、これがパイプラインのしくみについて最も役立つ説明であることがわかりました。


Azure WebJobでは[コンソール] :: WriteLineは機能しますが、Write-Hostはエラーになります:コンソール出力バッファーの文字属性の設定中に、Win32内部エラー「ハンドルが無効です」0x6が発生しました。理由を聞かないでください。
Gil Roitto

私が間違っている場合は修正してください。ただしWrite-Output、デフォルトであると考えています。たとえば、PsObjectがあり、これを実行して画面に吐き出した場合、$object実際にはこれと同じことを行いますWrite-Output $object。言及する価値があるかもしれません
コロブキャニオン

1
新しいガイダンスがありWrite-Outputます。可能な場合は使用しないでください。github.com/PoshCode/PowerShellPracticeAndStyle/issues/…を参照してください >実行を終了する場合のみreturnを使用します。>書き込み出力(...)を避けます。代わりに、出力をより明確にしたい場合は、関連する名前の変数に出力を割り当ててください。明示的な出力を通知するために、変数を単独で行に配置します。> Write-Output -NoEnumerateはPowerShell 6で機能しなくなり、16か月以上経過しています。これを修正する予定はありません。要約すると、>書き込み出力を使用しないでください-これまで。
Jeroen Wiert Pluimers

28

Andyが述べたこととは別に、重要な可能性のある別の違いがあります。write-hostはホストに直接書き込み、何も返さないため、出力をファイルなどにリダイレクトできません。

---- script a.ps1 ----
write-host "hello"

PowerShellで実行します。

PS> .\a.ps1 > someFile.txt
hello
PS> type someFile.txt
PS>

ご覧のように、それらをファイルにリダイレクトすることはできません。これは、注意深くない人にとってはおそらく驚くべきことです。

ただし、代わりに書き込み出力を使用するように切り替えた場合、リダイレクトは期待どおりに機能します。


Start-Process Powershellを使用すると、書き込みホスト出力をキャプチャできます。\ a.ps1 -RedirectStandardOutput somefile.txtただし、エンコーディングに問題があります(ファイルはSystemDefaultEncodingにあります)。
MKesper 2016年

16

Write-Outputと同等の機能を実現する別の方法を次に示します。文字列を引用符で囲みます。

"count=$count"

この実験を実行することで、これがWrite-Outputと同じように機能することを確認できます。

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

最初の2つは「何とか何とか」をout.txtに出力しますが、3番目は出力しません。

「help Write-Output」は、この動作のヒントを提供します。

このコマンドレットは通常、スクリプトで使用され、文字列やその他のオブジェクトをコンソールに表示します。ただし、既定の動作では、パイプラインの最後にオブジェクトを表示するため、通常、コマンドレットを使用する必要はありません。

この場合、文字列自体「count = $ count」はパイプラインの最後のオブジェクトであり、表示されます。


6

用法についてWrite-HostPSScriptAnalyzer次の診断を生成します。

Write-Hostすべてのホストで機能しない可能性があり、ホストがない場合は機能せず、(PS 5.0より前の)抑制、キャプチャー、またはリダイレクトできないため、使用を避けてください。代わりに、使用Write-OutputWrite-VerboseまたはWrite-Information

詳細については、そのルールの背後にあるドキュメントを参照してください。後世の抜粋:

使用がWrite-Host大幅に持つコマンドの使用でない限り推奨されてShow動詞。Show動詞は、明示的に「ノー他の可能性と、画面上のショーを、」意味します。

Show動詞を含むコマンドには、このチェックが適用されていません。

Jeffrey Snoverのブログ投稿Write-Host考慮された有害、自動化妨げ、診断の背後にあるより多くの説明を提供するため、Write-Hostはほとんど常に間違っていると主張していますが、上記は良い要約です。


3

私のテストでは、Write-Outputおよび[Console] :: WriteLine()はWrite-Hostよりもはるかに優れています。

書き出す必要のあるテキストの量によっては、これが重要になる場合があります。

5つの結果がWrite-Host、Write-Output、および[Console] :: WriteLine()に対してそれぞれテストされた場合、以下のようになります。

私の限られた経験では、コマンドレットを放棄して、スクリプトから適切なパフォーマンスを得るために、コマンドレットを破棄し、より低いレベルのコマンドに直接進む必要があるあらゆる種類の現実世界のデータを操作するときに気付きました。

measure-command {$count = 0; while ($count -lt 1000) { Write-Host "hello"; $count++ }}

1312ms
1651ms
1909ms
1685ms
1788ms


measure-command { $count = 0; while ($count -lt 1000) { Write-Output "hello"; $count++ }}

97ms
105ms
94ms
105ms
98ms


measure-command { $count = 0; while ($count -lt 1000) { [console]::WriteLine("hello"); $count++ }}

158ms
105ms
124ms
99ms
95ms

1
Write-Outputそして、Write-Host異なる目的を果たすため、彼らのパフォーマンスを比較しても意味がありません。はい、.NETタイプとそのメソッドを直接使用する方が高速ですが、PowerShellコマンドレットが提供できる高レベルの機能を見逃しています。手元のケース[Console]::WriteLine()と似てWrite-Hostいますが、すべてのPowerShellホストがコンソールではないため、すべての状況で動作するわけではありません。
mklement0

0

[Console] :: WriteLine()について-(Powershellではなく)CMDでパイプラインを使用する場合は、これを使用する必要があります。たとえば、ps1で大量のデータをstdoutにストリーミングし、他のユーティリティでそれを消費/変換したいとします。スクリプトでWrite-Hostを使用すると、速度が大幅に低下します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.