具有功能的管道的参数化
Parametrization of a pipe with a function
我发现 powershell 时有些高兴,有些沮丧,目前我在 powershell 能力方面碰壁了。
我想创建一个管道函数来汇总对象集合的成员类型。
没有函数,工作代码如下所示:
get-process |
foreach { get-member -inputobject $_ } |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object |
sort count, name
现在,我目前对实现此功能的尝试是:
function get-membersummary {
process {
get-member -inputobject $_ |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object |
sort count, name
}
}
应该这样使用:
&$anything | get-membersummary
明显的问题是"process"语句中的代码是针对每个元素调用的,也就是说对每个item进行了分组。我想要的是整两行分组的第一个结果。
是否可以在不使用会导致内存效率低下的数组变量的情况下在 powershell 中实现此目的?
另外,我很确定这个问题已经被问过了,但是我找不到合适的词来表达它。
您可以使用 SteppablePipeline
,但是对于排序,您必须在开始排序之前收集整个输入,因此在这里使用数组几乎不会比您已经拥有的更多 "memory inefficiency"。
function get-membersummary {
begin {
$Pipeline={
&foreach { get-member -inputobject $_ } |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object|
sort count, name
}.GetSteppablePipeline()
$Pipeline.Begin($MyInvocation.ExpectingInput,$ExecutionContext)
}
process {
if($MyInvocation.ExpectingInput){
$Pipeline.Process($_)
}else{
$Pipeline.Process()
}
}
end {
$Pipeline.End()
$Pipeline.Dispose()
}
}
接收到所有数据后才能进行分组排序,所以需要等到函数中的end {}
块。两个例子:
#process using pipeline, but wait until end to group and sort
function get-membersummary {
begin { $res = @() }
process {
$res += Get-Member -inputobject $_ |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
}
end {
$res | Group-Object | Sort-Object Count, Name | Select-Object Count, Name
}
}
#do everything after all objects have arrived
function get-membersummary2 {
end {
#in process { }, $input is the object in the pipeline. in end { } it is a collection of all the objects.
$input | % {
Get-Member -InputObject $_ |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
} | Group-Object | Sort-Object Count, Name | Select-Object Count, Name
}
}
Get-Process | get-membersummary | ft -AutoSize
#Get-Process | get-membersummary2 | ft -AutoSize
输出:
Count Name
----- ----
75 [AliasProperty]Handles
75 [AliasProperty]Name
75 [AliasProperty]NPM
75 [AliasProperty]PM
75 [AliasProperty]VM
75 [AliasProperty]WS
75 [Event]Disposed
75 [Event]ErrorDataReceived
75 [Event]Exited
75 [Event]OutputDataReceived
....
一般来说,您应该避免在函数中使用 Group-Object
和 Sort-Object
,因为它们会破坏管道的流程。 Select-Object
(我这次添加的)也应该避免,因为它会破坏原始对象。我理解在这种情况下的选择,但要注意不要过度使用它们。您可以编写一个函数或过滤器来处理对象,然后在需要时手动调用 group
和 sort
,例如:
filter get-membersummary3 {
$_ |
Get-Member |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
}
Get-Process | get-membersummary3 | Group-Object | Sort-Object Count, Name | Select-Object Count, Name
我发现 powershell 时有些高兴,有些沮丧,目前我在 powershell 能力方面碰壁了。
我想创建一个管道函数来汇总对象集合的成员类型。
没有函数,工作代码如下所示:
get-process |
foreach { get-member -inputobject $_ } |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object |
sort count, name
现在,我目前对实现此功能的尝试是:
function get-membersummary {
process {
get-member -inputobject $_ |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object |
sort count, name
}
}
应该这样使用:
&$anything | get-membersummary
明显的问题是"process"语句中的代码是针对每个元素调用的,也就是说对每个item进行了分组。我想要的是整两行分组的第一个结果。
是否可以在不使用会导致内存效率低下的数组变量的情况下在 powershell 中实现此目的?
另外,我很确定这个问题已经被问过了,但是我找不到合适的词来表达它。
您可以使用 SteppablePipeline
,但是对于排序,您必须在开始排序之前收集整个输入,因此在这里使用数组几乎不会比您已经拥有的更多 "memory inefficiency"。
function get-membersummary {
begin {
$Pipeline={
&foreach { get-member -inputobject $_ } |
foreach { "[$($_.membertype)]$($_.name)" } |
group-object|
sort count, name
}.GetSteppablePipeline()
$Pipeline.Begin($MyInvocation.ExpectingInput,$ExecutionContext)
}
process {
if($MyInvocation.ExpectingInput){
$Pipeline.Process($_)
}else{
$Pipeline.Process()
}
}
end {
$Pipeline.End()
$Pipeline.Dispose()
}
}
接收到所有数据后才能进行分组排序,所以需要等到函数中的end {}
块。两个例子:
#process using pipeline, but wait until end to group and sort
function get-membersummary {
begin { $res = @() }
process {
$res += Get-Member -inputobject $_ |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
}
end {
$res | Group-Object | Sort-Object Count, Name | Select-Object Count, Name
}
}
#do everything after all objects have arrived
function get-membersummary2 {
end {
#in process { }, $input is the object in the pipeline. in end { } it is a collection of all the objects.
$input | % {
Get-Member -InputObject $_ |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
} | Group-Object | Sort-Object Count, Name | Select-Object Count, Name
}
}
Get-Process | get-membersummary | ft -AutoSize
#Get-Process | get-membersummary2 | ft -AutoSize
输出:
Count Name
----- ----
75 [AliasProperty]Handles
75 [AliasProperty]Name
75 [AliasProperty]NPM
75 [AliasProperty]PM
75 [AliasProperty]VM
75 [AliasProperty]WS
75 [Event]Disposed
75 [Event]ErrorDataReceived
75 [Event]Exited
75 [Event]OutputDataReceived
....
一般来说,您应该避免在函数中使用 Group-Object
和 Sort-Object
,因为它们会破坏管道的流程。 Select-Object
(我这次添加的)也应该避免,因为它会破坏原始对象。我理解在这种情况下的选择,但要注意不要过度使用它们。您可以编写一个函数或过滤器来处理对象,然后在需要时手动调用 group
和 sort
,例如:
filter get-membersummary3 {
$_ |
Get-Member |
ForEach-Object { "[$($_.MemberType)]$($_.Name)" }
}
Get-Process | get-membersummary3 | Group-Object | Sort-Object Count, Name | Select-Object Count, Name