iRo*_*Ron 1 powershell pipeline select-object
Strongly Encouraged Development Guidelinescmdlet 应该为管道中间实现的 PowerShell ,但我怀疑-Last对于Select-Object. 仅仅是因为您无法预先确定最后一个条目。换句话说:您需要等待输入流完成,直到您定义最后一个条目。
为了证明这一点,我写了一个小脚本:
$Data = 1..5 | ForEach-Object {[pscustomobject]@{Index = "$_"}}
$Data | ForEach-Object { Write-Host 'Before' $_.Index; $_ } |
Select-Object -Last 5 | ForEach-Object { Write-Host 'After' $_.Index }
Run Code Online (Sandbox Code Playgroud)
并将其与Select-Object *:
$Data | ForEach-Object { Write-Host 'Before' $_.Index; $_ } |
Select-Object * | ForEach-Object { Write-Host 'After' $_.Index }
Run Code Online (Sandbox Code Playgroud)
结果(右:Select-Object -Last 5,左:)Select-Object *:
-Last 5 *
------- -
Before 1 Before 1
Before 2 After 1
Before 3 Before 2
Before 4 After 2
Before 5 Before 3
After 1 After 3
After 2 Before 4
After 3 After 4
After 4 Before 5
After 5 After 5
Run Code Online (Sandbox Code Playgroud)
尽管没有记录在案,但我认为我可以由此得出结论,该-Last参数确实阻塞了管道。
这没什么大不了的,但我也对-First参数进行了测试,并得到了一些令人不安的结果。为了更好地展示这一点,我没有选择所有对象,而只是选择 ** -First 2**:
$Data | ForEach-Object { Write-Host 'Before' $_.Index; $_ } |
Select-Object -First 2 | ForEach-Object { Write-Host 'After' $_.Index }
Before 1
After 1
Before 2
After 2
Run Code Online (Sandbox Code Playgroud)
请注意,使用该-First 2参数时,不仅后面的 cmdlet 显示两个对象,而且前面的 cmdlet 只显示两个对象。
显然,-First参数直接引用到先前 cmdlet 的对象中,这与使用-Last 2参数不同:
$Data | ForEach-Object { Write-Host 'Before' $_.Index; $_ } |
Select-Object -Last 2 | ForEach-Object { Write-Host 'After' $_.Index }
Before 1
Before 2
Before 3
Before 4
Before 5
After 4
After 5
Run Code Online (Sandbox Code Playgroud)
使用cmdletOut-Host代替Write-Hostcmdlet 或将结果发送到变量时也会发生这种情况,例如:
$Before = ""; $After = ""
$Data | ForEach-Object { $Before += $_.Index; $_ } | Select-Object -First 2 | ForEach-Object { $After += $_.Index }
$Before
$After
Run Code Online (Sandbox Code Playgroud)
这显示在 Windows Powershell ( 5.1.18362.628) 和 PowerShell Core ( 7.0.0) 上。
这是一个错误吗?
Select-Object通过作弊影响上游命令这听起来可能是个笑话,但事实并非如此。
为了优化管道流性能,Select-Object使用了一个普通用户无法使用的技巧Cmdlet,它会抛出一个StopUpstreamCommandsException.
一旦捕获,运行时(间接地)调用StopProcessing()的所有上面的命令,但不把它作为一个终止错误事件,允许下游cmdlet来继续执行。
当您在管道早期执行缓慢或计算量大的命令时,这非常有用:
# this will only take ~3 seconds to return with the StopUpstreamCommand behavior
# but would have incurred 8 extra seconds of "waiting to discard" otherwise
Measure-Command {
1..5 |ForEach-Object { Start-Sleep -Seconds 1; $_ } |Select-Object -First 3
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
368 次 |
| 最近记录: |