I often have the following situation in my PowerShell code: I have a function or property that returns a collection of objects, or $null
. If you push the results in
Another possibility:
$objects | Foreach-Object -Begin{If($_ -eq $null){continue}} -Process {do your stuff here}
More info in about_Continue
I don't think anyone likes the fact that both "foreach ($a in $null) {}" and "$null | foreach-object{}" iterate once. Unfortunately there is no other way to do it than the ways you have demonstrated. You could be pithier:
$null | ?{$_} | % { ... }
the ?{$_}
is shorthand for where-object {$_ -ne $null}
as $null
evaluated as a boolean expression will be treated as $false
I have a filter defined in my profile like this:
filter Skip-Null { $_|?{ $_ } }
Usage:
$null | skip-null | foreach { ... }
A filter is the same as a function except the default block is process {} not end {}.
UPDATE: As of PowerShell 3.0, $null
is no longer iterable as a collection. Yay!
-Oisin
A quick note to Keith's answer to complete it
Personally, I would return nothing. It makes sense:
PS> function Empty { if ('a' -eq 'b') { 'equal' } }
PS> Empty | % { write-host result is $_ }
But now you are in problems if you assign result from Empty
to a variable:
PS> $v = Empty
PS> $v | % { write-host result is $_ }
There is a little trick to make it work. Just wrap the result from Empty
as a array like this:
PS> $v = @(Empty)
PS> $v | % { write-host result is $_ }
PS> $v.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS> $v.Length
0
If you can modify your function, have it return an empty collection/array instead of $null:
PS> function Empty { $null }
PS> Empty | %{'hi'}
hi
PS> function Empty { @() }
PS> Empty | %{'hi'}
Otherwise, go with what Oisin suggests although I would suggest a slight tweak:
filter Skip-Null { $_|?{ $_ -ne $null } }
Otherwise this will also filter 0
and $false
.
Update 4-30-2012: This issue is fixed in PowerShell v3. V3 will not iterate over a scalar $null value.