防止 PowerShell ForEach-Object 扁平化列表? [英] Prevent PowerShell ForEach-Object to flatten the list?

查看:71
本文介绍了防止 PowerShell ForEach-Object 扁平化列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code prints the counts if there are more than two items. The .Split(',') was called twice.

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

以下代码尝试调用一次 .Split(',').它没有得到任何输出.

The following code try to call .Split(',') once. It doesn't get any output.

'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-Objectlist of list 扁平化为list.有没有防止扁平化的方法?

However, ForEach-Object flattens the list of list to list. Is it a way to prevent the flattening?

推荐答案

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

You can take advantage of the fact that both Where-Object and ForEach-Object run the script blocks passed to them ({ ... }) in the same scope, the caller's scope:

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

也就是说,在 Where-Object 脚本块中分配给的 $count 变量可在 ForEach-Object 脚本中访问块也是一样,输入对象一个输入对象.

That is, the $count variable that is assigned to in the Where-Object script block is accessible in the ForEach-Object script block as well, input object by input object.

也就是说,您可以单独使用 ForEach-Object 完成所有需要:

That said, you can do all you need with ForEach-Object alone:

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

请注意,我已从 .Split() 方法 切换到使用 PowerShell 的 更灵活 -split operator.

Note that I've switched from the .Split() method to using PowerShell's more flexible -split operator.

至于你尝试了什么:

将数组(可枚举)输出到管道会导致其元素被一个接一个发送,而不是作为一个完整的数组.

Outputting an array (enumerable) to the pipeline causes its elements to be sent one by one rather than as a whole array.

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

The simplest way to avoid that, i.e, to send an array as a whole, is to wrap such an array in an auxiliary single-element wrapper array, using the unary form of ,, the array-construction operator: , $_.Split(',')

请注意,@(...) 中包含命令不会执行相同的包装,因为 @(...)构造一个数组;松散地说,它只是确保输出是一个数组,所以如果输入已经一个数组 - 就像你的情况 - @(...) 是 - 松散地说 - (昂贵的)no-op - 请参阅 此答案 了解详情.

Note that enclosing a command in @(...) does not perform the same wrapping, because @(...) doesn't construct an array; loosely speaking, it merely ensures that the output is an array, so if the input already is an array - as in your case - @(...) is - loosely speaking - a (costly) no-op - see the bottom section of this answer for details.

这篇关于防止 PowerShell ForEach-Object 扁平化列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆