为了补充大卫马丁的有用答案:
实际上,Write-Host
它用于直接写入主机,即基于控制台窗口的 PowerShell 会话中的控制台(终端)。也就是说,Write-Host
故意绕过PowerShell 的成功输出流,命令和表达式隐含地将其数据发送到该输出流。
Write-Output
是写入成功输出流的 cmdlet,但很少需要显式使用它;你可以直接使用"show 1"
和"show 2"
原样。
Write-Host
用于创建用户界面(打印(彩色)消息以通知用户),而不是用于输出数据。
有关更多信息,请参阅此答案的底部。
脚本块 ( { ... }
) 通常&
在参数(解析)模式(如 cmdlet 和外部程序)中使用调用运算符调用,而不是通过它们的方法调用,这允许更熟悉的语法;例如:.Invoke()
& $test_block
而不是$test_block.Invoke()
- 带参数:
& $test_block arg1 ...
而不是$test_block.Invoke(arg1, ...)
也许更重要的是,使用这种基于运算符的调用语法(& { ... } ...
或. { ... } ...
)具有以下优点:
它保留了正常的流式语义,这意味着成功输出(也)在脚本块生成时从脚本块发出,而在一个实例中.Invoke()
首先收集所有成功输出,然后返回 - 相比之下,输出直接到两种情况下都显示。[System.Collections.ObjectModel.Collection[psobject]]
Write-Host
作为一个有益的副作用,您的特定输出排序问题消失了,但请注意,在PSv5+ 中通常仍然可能存在输出排序问题,尽管其原因无关:对于没有预定义格式数据的输出类型的隐式表格输出(隐含)是异步的,以确定合适的列宽(您的特定代码恰好只使用具有预定义格式数据的 cmdlet)。Format-Table
有关更多信息,请参阅此答案;一个简单的复制:
[pscustomobject] @{ foo = 1 }; Write-Host 'Should print after, but prints first.'
它允许您传递命名参数(例如-Foo Bar
),而.Invoke()
仅支持位置(未命名)参数(例如Bar
)。
它保留了脚本终止错误的正常语义:
# OK: & throw aborts the entire script; 'after' never prints.
& { throw 'fatal' }; 'after'
# !! .Invoke() "eats" the script-terminating error and
# !! effectively converts it to a *statement*-terminating one.
# !! Therefore, execution continues, and 'after' prints.
{ throw 'fatal' }.Invoke(); 'after'
此外,使用基于操作符的调用为您提供了使用.
点源操作符代替 的选项&
,以便直接在调用者的范围内运行脚本块,而.Invoke()
方法调用仅在子&
范围内运行(如):
# Dot-sourcing the script block runs it in the caller's scope.
. { $foo='bar' }; $foo # -> 'bar'
使用.Invoke()
最好仅限于 PowerShell SDK 项目(通常基于 C#,不能选择使用 PowerShell 运算符)。