Powershell echo vs write-host和不同的输出

use*_*921 4 powershell

我正在尝试编写我的第一个脚本但是我遇到了一些与PowerShell有关的问题.

我使用以下代码:

$Disk = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and $_.Size -lt 200Gb -and -not $_.IsBoot }
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么

PS C:\> echo $disk
Number Friendly Name                            OperationalStatus                    Total Size Partition Style
 ------ -------------                            -----------------                    ---------- ---------------
1      Imation IronKey Wkspace USB Device       Online                                 59.63 GB MBR
Run Code Online (Sandbox Code Playgroud)

PS C:\> write-host $disk
MSFT_Disk (ObjectId = "\\?\usbstor#disk&ven_imation&prod_ironk...)
Run Code Online (Sandbox Code Playgroud)

以下powershell脚本更复杂:

$Disk = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and $_.Size -lt 200Gb -and -not $_.IsBoot }
$WIM = Get-PSDrive -PSProvider FileSystem | Where { Test-Path (join-path $_.Root "\sources\install.wim") }
echo $Disk
echo $WIM
Write-Host $WIM
Write-Host $Disk
Run Code Online (Sandbox Code Playgroud)

然后改变回声的顺序并写入我获得不同的输出

谁能解释发生了什么?

Ant*_*ace 7

在PowerShell中,echo映射到Write-Output而不是Write-Host.如果要输出某些操作产生的对象,则应输出它们而不是尝试输出Write-Host.写入的内容Write-Host不会使其成为输出流,因此您不能(例如)在后续调用或管道中使用它.

你看到那个令人讨厌的乱码输出,Write-Host因为它试图写出整个对象,并且不明白你可能更喜欢一个带有干净列出属性的漂亮表.您应该保留Write-Host当您需要向用户传达一些您不介意被消费的简单信息时,即使这样,也可能有更好的替代方案,如Write-DebugWrite-Verbose.

更多信息在这里.

您可以通过使用Help或调用cmdlet来检查这样的映射Get-Help:

PS C:\> help echo

NAME
    Write-Output
Run Code Online (Sandbox Code Playgroud)


Dun*_*can 5

Write-Host小命令输出到主机(即,的powershell或ISE窗口).它接受一个对象作为输入,并简单地调用.ToString()对象的方法(或者它是一个它调用的数组.ToString()或数组的每个元素.

Write-Output或者它的别名echo只是将输入对象写入当前管道.然后,从当前函数,cmdlet或脚本返回到达管道末端的任何对象(如果有的话)(然后它们可以继续沿着某个其他管道继续).最终,对象可能会到达不在函数,cmdlet或脚本内部的管道的末尾,并且它们似乎会输出到主机.实际发生的是,在最外层管道的末尾,所有对象都被发送到一个额外的隐藏cmdlet : Out-Default.

Out-Default将对象发送到默认格式化程序,然后发送默认输出cmdlet.这是默认的格式化你的磁盘对象转换成一堆FormatStartData,GroupStartData,FormatEntryData,GroupEndData,和FormatEndData对象(管像输出Format-TableGet-Member看这些对象).最后,格式对象是发送到主机以生成格式化输出的内容.

如果您想要一些乐趣,请尝试重新定义,Out-Default以便您可以看到它的调用位置:

PS C:\scripts> function Out-Default {
>>   Write-Verbose "Called Out-Default" -Verbose
>>   $input | Format-Table | Out-Host
>> }
>>
PS C:\scripts> cd mod2
VERBOSE: Called Out-Default
PS C:\scripts\mod2> ls
VERBOSE: Called Out-Default


    Directory: C:\scripts\mod2


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        29/12/2013     11:00        308 1Var.ps1
-a---        29/12/2013     11:00        326 2Quotes.ps1
-a---        29/12/2013     11:00        416 3ObjectMembers.ps1
-a---        29/12/2013     11:00        665 4Parenthesis.ps1
-a---        29/12/2013     11:00        392 5If.ps1
-a---        29/12/2013     11:00        325 6Switch.ps1
-a---        29/12/2013     11:00        226 7Do_While.ps1
-a---        29/12/2013     11:00        272 8For_Foreach.ps1
-a---        29/12/2013     11:00        150 _Startup.ps1
Run Code Online (Sandbox Code Playgroud)