使用 Sort-Object 时的 Powershell 管道变量 lost/overwritten。选择?

Powershell pipelinevariable lost/overwritten when using Sort-Object. alternative?

我是 运行 管道中的一系列 cmdlet,为每个 cmdlet 设置了一个 -PipeLineVariable,但由于在管道中使用了 Sort-Object cmdlet,我得到了意想不到的结果。

以示例代码为例,这只是我完整代码的一部分。 Get-VMhost 正在拉取随机主机,但我的 OCD 想要一个按字母顺序排列的列表并且只想 select 前 2 个。因此我在 Get-VMhost 之后添加一个排序对象,但这会破坏管道变量最后。

get-vmhost -PipelineVariable VMHost | sort Name | select -first 2 | % {write-host $vmhost} 

VMHost3
VMHost3

相反,我希望看到

VMHost1
VMHost2

我理解这是某些 cmdlet(例如 Sort-Object)的结果,因为它们必须聚合所有要处理的输入,然后中断流。我有点明白了。

不使用...

Select -First 2

...我将获得整个数据集,我可以简单地排序作为我对所有数据进行排序的最后一步。我也可以在末尾添加 select -first 2 。 我只是想了解问题及其发生的原因,以及是否有预先的内联解决方法。

***编辑...我有我的答案,就是在排序语句中设置管道变量。谢谢@mklement0

您问题中的代码表现符合预期/设计(见下文)。

我不确定你想要实现什么,但你可能想要以下内容:

$myVMs = get-vmhost | sort Name | select -first 2
$myVMs | ForEach-Object { write-host $_ }

或者,在单个管道中:

get-vmhost | sort Name | select -first 2 | ForEach-Object { write-host $_ }

参考:about_CommonParameters

PipelineVariable allows access to the most recent value passed into the next pipeline segment by the command that uses this parameter. Any command in the pipeline can access the value using the named PipelineVariable. The value is assigned to the variable when it is passed into the next pipeline segment. This makes the PipelineVariable easier to use than a specific temporary variable, which might need to be assigned in multiple locations.

Unlike $_ or $PSItem, using a PipelineVariable allows any pipeline command to access pipeline values passed (and saved) by commands other than the immediately preceding command. Pipeline commands can access the last value piped from while processing the next item passing through the pipeline. This allows a command to feed back its output to a previous command (or itself).

Caution

The PipelineVariable is scoped to the pipeline in which it is invoked. Variables outside the pipeline, which use same name, are removed before the pipeline is executed. The PipelineVariable goes out of scope when the pipeline terminates. If multiple commands within the pipeline specify the same PipelineVariable then there is only one shared variable. That variable is updated with the most recent piped output from the command that specifies the variable.

Some blocking commands collect all the pipeline items before producing any output, for example Sort-Object or Select-Object -Last. Any PipelineVariable assigned in a command before such a blocking command always contains the final piped item from the preceding command when used in a command after the blocking command.

您只需将 common -PipelineVariable parameter Sort-Object cmdlet 一起使用而不是 Get-VMHost 即可让管道变量反映已排序 对象序列。

一个简化的例子:

3, 6, 2, 1 | Sort-Object -PipelineVariable value | Select-Object -First 2 |
  ForEach-Object { $value }

输出:

1
2