Powershell 中的管道 Select-Object 示例Sort-Object 示例

如何解决Powershell 中的管道 Select-Object 示例Sort-Object 示例

我在 about_Pipelines 阅读了有关管道在 PowerShell 中的工作原理的文章,并了解到管道一次传送一个对象。

所以,这个

Get-Service | Format-Table -Property Name,DependentServices

与此不同

Format-Table -InputObject (Get-Service) -Property Name,DependentServices

因此,按照解释,在第一种情况下,Format-Table 一次作用于一个对象,而在第二个示例中,Format-Table 作用于一组对象。如果我错了,请纠正我。

如果是这种情况,那么我想知道 sort-object 和其他需要处理数据集合的 cmdlet 是如何处理管道字符的。

当我这样做时:

Get-Service | sort-object

如果 sort-object 一次只处理一个对象,它如何能够排序。因此,假设有 100 个服务对象要传递给 sort-objectsort-object 会被调用 100 次(每次调用一个对象)吗?而且,这将如何产生我在屏幕上看到的排序结果。

解决方法

Sort-Object(以及其他需要在输出任何内容之前评估所有输入对象的 cmdlet)通过一个一个地收集输入对象来工作,然后在上游之前不做任何实际工作cmdlet(在本例中为 Get-Service)已完成发送输入。

这是如何工作的?好吧,让我们尝试使用 PowerShell 函数重新创建 Sort-Object

为此,我们首先需要了解一个 cmdlet 由 3 个独立的例程组成:

  • Begin - 管道中每个 cmdlet 的 Begin 例程在发生任何其他事情之前调用一次
  • Process - 在每个 cmdlet 上调用此例程每次收到来自上游命令的输入
  • End - 一旦上游命令调用 End 并且没有更多输入项供 Process 处理

(这些是 PowerShell function 定义中使用的块标签名称 - 在二进制 cmdlet 中,您将覆盖 BeginProcessingProcessRecord、{{3} } cmdlet 的方法)

因此,要“收集”每个输入项,我们需要在命令的 Process 块中添加一些逻辑,然后我们可以将操作所有项的代码放在 {{1} } 块:

End

如果我们用 function Sort-ObjectCustom { param( [Parameter(Mandatory,ValueFromPipeline)] [object[]]$InputObject ) begin { # Let's use the `begin` block to create a list that'll hold all the input items $list = [System.Collections.Generic.List[object]]::new() Write-Verbose "Begin was called" } process { # Here we simply collect all input to our list $list.AddRange($InputObject) Write-Verbose "Process was called [InputObject: $InputObject]" } end { # The `end` block is only ever called _after_ we've collected all input # Now we can safely sort it $list.Sort() Write-Verbose "End was called" # and output the results return $list } } 调用我们的新命令,我们将看到输入是如何一一收集的:

-Verbose

有关如何为二进制 cmdlet 实现管道输入处理例程的详细信息,请参阅 EndProcessing

有关如何在函数中利用相同管道语义的更多信息,请参阅 "How to Override Input Processing"

,

为了补充来自 Mathias 的答案,您实际上可以使用 Write-Host cmdlet 从现有 cmdlet 中可视化进程的顺序,该 cmdlet 立即将输出写入显示器(而不是管道):

$Data = ConvertFrom-Csv @'
Id,Name
 4,Four
 2,Two
 3,Three
 1,One
'@

Select-Object 示例

$Data |
    Foreach-Object { Write-Host 'in:' ($_ |ConvertTo-Json -Compress); $_ } |
    Select-Object * |
    Foreach-Object { Write-Host 'out:' ($_ |ConvertTo-Json -Compress); $_ }

节目:

in: {"Id":"4","Name":"Four"}
out: {"Id":"4","Name":"Four"}

in: {"Id":"2","Name":"Two"}
out: {"Id":"2","Name":"Two"}
in: {"Id":"3","Name":"Three"}
out: {"Id":"3","Name":"Three"}
in: {"Id":"1","Name":"One"}
out: {"Id":"1","Name":"One"}
Id Name
-- ----
4  Four
2  Two
3  Three
1  One

Sort-Object 示例

$Data |
    Foreach-Object { Write-Host 'in:' ($_ |ConvertTo-Json -Compress); $_ } |
    Sort-Object * |
    Foreach-Object { Write-Host 'out:' ($_ |ConvertTo-Json -Compress); $_ }

节目:

in: {"Id":"4","Name":"Four"}
in: {"Id":"2","Name":"One"}

out: {"Id":"2","Name":"Two"}
out: {"Id":"3","Name":"Three"}
out: {"Id":"4","Name":"Four"}
Id Name
-- ----
1  One
2  Two
3  Three
4  Four

一般来说,PowerShell cmdlet Write Single Records to the Pipeline 在可能的情况下(此鼓励指南的优点之一是它减少了内存消耗)。正如您的问题所暗示的那样, Sort-Object 不能这样做,因为最后一条记录可能出现在第一条记录之前。但也有例外,在技术上可以根据鼓励的准则编写单个记录,但事实并非如此。参见例如:#11221 Select-Object -Unique is unnecessary slow and exhaustive

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?