问题描述
如果有两个以上的项目,以下代码会打印计数..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-Object
将list of list
扁平化为list.有没有防止扁平化的方法?
However, ForEach-Object
flattens the list of list
to list. Is it a way to prevent the flattening?
推荐答案
您可以利用 Where-Object
和 ForEach-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 } }
至于你尝试了什么:
将数组(可枚举)输出到管道会导致其元素被一个接一个发送,而不是作为一个完整的数组.
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 扁平化列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!