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 }
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.
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 } }
Note that I've switched from the .Split()
method to using PowerShell's more flexible -split
operator.
As for what you tried:
Outputting an array (enumerable) to the pipeline causes its elements to be sent one by one rather than as a whole array - see this answer for background information.
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(',')
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.