如果有两个以上的项目,以下代码将打印计数。 .Split(',')被调用了两次。

'a,b,c', 'x,y', '1,2,3' |
Where-Object { $_.Split(',').Count -gt 2 } |
ForEach-Object { $x = $_.Split(','); $x.Count }

以下代码尝试一次调用.Split(',')。它没有任何输出。
'a,b,c', 'x,y', '1,2,3' |
ForEach-Object { @($_.Split(',')) } | # got a single list instead of `list of list of string`
Where-Object { $_.Count -gt 2 } |
ForEach-Object { $_.Count }

但是,ForEach-Object使list of list变平以列出。这是防止扁平化的方法吗?

最佳答案

您可以利用Where-ObjectForEach-Object都在同一范围(调用者的范围)中运行传递给它们的脚本块({ ... })的事实:

'a,b,c', 'x,y', '1,2,3', 'a,b,c,d' |
  Where-Object { ($count = $_.Split(',').Count) -gt 2 } |
    ForEach-Object { $count }

即,在$count脚本块中也可以通过输入对象逐个访问在Where-Object脚本块中分配的ForEach-Object变量。

就是说,您可以仅使用ForEach-Object来完成所有需要的工作:
'a,b,c', 'x,y', '1,2,3', 'a,b,c,d' |
  ForEach-Object { $count = ($_ -split ',').Count; if ($count -gt 2) { $count } }

请注意,我已经从.Split()方法切换为使用PowerShell的more flexible -split运算符。

至于您尝试了什么:

向管道输出数组(可枚举)会导致其元素被一一发送,而不是整个数组

避免这种情况的最简单方法,即整体发送一个数组,是使用一元形式, (数组构造运算符:, $_.Split(','))将此类数组包装在辅助单元素包装器数组中

请注意,将命令包含在@(...)中的不会执行相同的包装,因为 @(...)不会构造数组。松散地说,它仅确保输出是一个数组,因此,如果输入已经是一个数组-如您的情况-@(...)是-松散地说-一个(昂贵的)无操作-有关详细信息,请参见this answer的底部。

07-24 09:39
查看更多