解决方法
我的意思是什么?首先,让我们解决您的文档问题.以下内容来自PowerShell version 3.0 Language Specification第3.13段:
If a command writes a single object,its successor receives that@H_502_25@ object and then terminates after writing its own object(s) to its@H_502_25@ successor. If,however,a command writes multiple objects,they are@H_502_25@ delivered one at a time to the successor command,which executes once@H_502_25@ per object. This behavior is called streaming. In stream processing,@H_502_25@objects are written along the pipeline as soon as they become@H_502_25@ available,not when the entire collection has been produced.
When processing a collection,a command can be written such that it@H_502_25@ can do special processing before the initial element and after the@H_502_25@ final element.
现在,让我们简要了解一下cmdlet的组成.
Cmdlet及其构建块
将cmdlet视为另一个函数,每次调用时要同步执行的一组连续语句可能很诱人.然而,这是不正确的.
PowerShell中的cmdlet是一个实现至少3种方法之一的对象:
> BeginProcessing() – 当管道开始执行时运行一次@H_502_25@> ProcessRecord() – 为收到的每个管道项目运行@H_502_25@> EndProcessing() – 在处理完最后一个管道项后运行一次
管道开始执行后,将在管道中的每个cmdlet上调用BeginProcessing().从这个意义上说,管道中的所有cmdlet都是“并行”运行的 – 但是这种设计基本上允许我们用单个线程执行管道 – 因此不需要按照设计执行管道的涉及多个线程的实际并行处理.
可能更准确地指出cmdlet在管道中并发执行.
我们来试试吧!
由于上述三种方法直接映射到我们可以在高级函数中定义的begin,process和end块,因此很容易看到此执行流程的效果.
让我们尝试将10个对象提供给由三个cmdlet组成的管道,并使用Write-Host报告它们的状态,看看会发生什么(请参阅下面的代码):
PS C:\> 1..10 |first |second |third |Out-Null
请注意,PowerShell通过-OutBuffer通用参数支持外部输出缓冲控制,这也会影响执行流程:
希望这有一定道理!
这是我为上面的演示编写的代码.
以下函数的Write-Host输出将根据我们使用的别名更改其颜色,因此在shell中更容易区分.
function Test-Pipeline { param( [Parameter(ValueFromPipeline)] [psobject[]]$InputObject ) begin { $WHSplat = @{ ForegroundColor = switch($MyInvocation.InvocationName){ 'first' { 'Green' } 'second' { 'Yellow' } 'third' { 'Red' } } } Write-Host "Begin $($MyInvocation.InvocationName)" @WHSplat $ObjectCount = 0 } process { foreach($Object in $InputObject) { $ObjectCount += 1 Write-Host "Processing object #$($ObjectCount) in $($MyInvocation.InvocationName)" @WHSplat Write-Output $Object } } end { Write-Host "End $($MyInvocation.InvocationName)" @WHSplat } } Set-Alias -Name first -Value Test-Pipeline Set-Alias -Name second -Value Test-Pipeline Set-Alias -Name third -Value Test-Pipeline