3

在 PowerShell 中,管道中 cmdlet 的执行顺序似乎没有以明显的方式执行。似乎不是每个 cmdlet 执行然后将结果传递给管道中的下一个 cmdlet,而是在执行前一个 cmdlet 完成之前将 cmdlet 的各个输出对象传递给下一个 cmdlet 的输入。以下证实了这种行为:

1..5 | %{ Write-Host $_; $_ } | %{ Write-Host ([char]($_ + 64)) }

印刷

1
A
2
B
3
C
4
D
5
E

似乎正在发生的事情是ForEach-Objectcmdlet 的每次执行都将在迭代之前执行其脚本块和其管道中的每个后续命令。

这是实际发生的情况吗?这种行为是否记录在任何地方?对于所有迭代 cmdlet ForEach-Object(例如Where-Object,等),都是这种情况吗?

(1..5 | %{ Write-Host $_; $_ }) | %{ Write-Host ([char]($_ + 64)) }我知道我可以将片段包装在表达式 (整个集合到管道中的下一个命令?

4

2 回答 2

4

这符合我对管道如何处理对象的理解。在触及下一个项目之前,对象会在管道中“尽可能远”地移动。一些 cmdlet 不使用“进程”块,而是在必要时使用“结束”块(例如,排序对象必须拥有所有项目才能实际执行排序),因此它们会阻塞管道。其他人使用写输出(你的第二个 $_ 正在隐式执行)并保持管道移动。

于 2012-07-27T19:36:22.757 回答
1

每个对象都尽可能地通过管道。这就是为什么每个 cmdlet 都应该将其输出直接写入管道而不是将其累积在某个内部存储中,除非它必须像 Sort-Object 一样将所有输入一起处理。

它也有一些有趣的副作用。例如,如果 Get-Member cmdlet 从管道获取输入,则它会给出不同的输出;如果它从 InputObject 参数获取输入,则它会给出不同的输出。

而且,因为它是 PowerShell,所以都记录在这里:

Get-Help about_pipelines
于 2017-01-21T21:25:32.620 回答