PowerShell:如何获取管道收集的计数?

PowerShell:如何获取管道收集的计数?,powershell,count,size,Powershell,Count,Size,假设我有一个生成对象集合的进程。对于一个非常简单的例子,请考虑 $(1×get成员)< /C>。我可以得到生成的对象数: PS C:\WINDOWS\system32> $(1 | get-member).count 21 或者我可以用这些东西做点什么 PS C:\WINDOWS\system32> $(1 | get-member) | ForEach-object {write-host $_.name} CompareTo Equals ... 只有21个对象,执行上述操作

假设我有一个生成对象集合的进程。对于一个非常简单的例子,请考虑<代码> $(1×get成员)< /C>。我可以得到生成的对象数:

PS C:\WINDOWS\system32> $(1 | get-member).count
21
或者我可以用这些东西做点什么

PS C:\WINDOWS\system32> $(1 | get-member) | ForEach-object {write-host $_.name}
CompareTo
Equals
...
只有21个对象,执行上述操作没有问题。但是,如果这个过程生成了数十万个对象呢?然后,我不想只运行一次进程来计算对象,然后再次运行它来执行我想对它们执行的操作。那么,我怎样才能获得一个集合中沿管道发送的对象数呢

A之前被询问过,接受的答案是在集合上工作的脚本块内使用一个计数器变量。问题是我已经有了那个计数器,我要做的是检查计数器的结果是否正确。所以我不想只在脚本块中计数。我想要一个单独的、独立的度量我在管道中发送的集合的大小的方法。我该怎么做?

如果需要处理和计数:

ForEach对象
脚本块中进行自己的计数是避免两次处理的最佳选择

问题是我已经有了那个计数器,我要做的是检查计数器的结果是否正确

ForEach对象
可为每个输入对象可靠地调用,包括
$null
值,因此无需重复检查

如果希望更清晰地分离处理和计数,可以将多个
-Process
脚本块传递给
ForEach对象
(在本例中,
{$\u1}
是输入处理脚本块,
{++$count}
是输入计数脚本块):

注意,由于每个对象的参数绑定中的一个怪癖,实际上需要传递
-Begin
-End
脚本块才能传递多个
-Process
(每个输入对象)块;如果您实际上不需要
-Begin
和/或
-End
,请传递
$null
-请参阅

还要注意,
$count
变量存在于调用者的作用域中,并且不适用于
ForEach对象
调用;也就是说,
$count=0
可能会更新先前存在的
$count
变量,如果它以前不存在,则在调用
ForEach对象后继续存在


如果只需要计数:

是用于管道[1]中的大型流式输入集合的cmdlet:

下面的示例逐个生成100000个整数,并让
Measure Object
逐个对它们进行计数,而不在内存中收集整个输入

PS>(&{$i=0;while($i-lt 1e5){(+$i)}}度量对象)。计数
100000
注意事项
测量对象
忽略输入集合中的
$null
值-请参阅

请注意,虽然计数输入对象是
度量对象的默认行为,但它也支持多种其他操作,例如求和
-Sum
和求平均(
-Average
),可以选择在单个调用中组合



[1]
Measure Object
作为一个cmdlet,能够以流式方式处理输入,这意味着它在接收对象时一个接一个地对接收到的对象进行计数,这意味着即使是非常大的流式输入集(这些输入集也是一个接一个地创建的,例如使用
导入CSV
枚举大型CSV文件的行)可以在没有内存不足风险的情况下进行处理—无需将输入集合作为一个整体加载到内存中。但是,如果(a)输入集合已经在内存中,或者(b)它可以放入内存并且性能很重要,那么使用
(…).Count

1)您说没有理由检查,因为
ForEach对象
被可靠地调用。但是需要检查是因为我的脚本块中存在潜在错误。所以我想我现在明白了,因为管道是如何工作的,如果我需要在流程A的输出上运行流程B并检查流程B是否存在此类错误,那么我确实需要(A)将流程A的输出保存到一个数组并获得数组的大小,(B)使用流程B中的计数器将流程A的输出单独管道到流程B,以及(c)比较(A)中的大小使用(b)中的计数器。这需要运行两次,但这是错误检查的成本。这有意义吗?2)你说使用
测量对象
。但是为什么要这样做而不是仅仅计算呢?换句话说,为什么
($array | measure object).count
当您可以执行
$array.count
?@NewSites:Re 2)
作为cmdlet,可以以流式方式处理输入,这意味着它可以在接收对象时逐个统计对象,这意味着即使是非常大的输入集(也可以逐个创建,例如使用
导入CSV
枚举大型CSV文件的行),也可以在没有内存耗尽风险的情况下进行处理-无需将输入集合作为一个整体加载到内存中。如果(a)输入集合已经在内存中,或者(b)它可以放入内存并且性能很重要,那么一定要使用
.Count
.Re 1)我不确定我是否完全理解,但是请注意,您可以在
ForEach对象
脚本块内部执行错误处理。也就是说,您可以根据需要检测/捕获/忽略错误并执行条件计数。我发现try-catch并不总是捕获所有错误!看见因此,我正在仔细观察并检查我的结果。但是现在我想知道我是否可以接受你的回答中关于传递多个
进程
块的内容,以及你的评论中关于
测量对象
以流式方式工作的内容,并结合这些内容对进程a的输出进行计数,与But并行
PS> 1..5 | ForEach-Object -Begin { $count = 0 } `
                          -Process { $_ + 1 }, { ++$count } `
                          -End { "--- count: $count" }

2
3
4
5
6
--- count: 5