我的PowerShell代码中经常出现以下情况:我有一个返回对象集合的函数或属性,或$null
。如果将结果推送到管道中,那么如果$null
是唯一的元素,您还可以处理管道中的元素。
示例:
$Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" }
如果没有功能($ Project.Features返回$ null),您将看到一行“功能名称:”。
我认为有三种方法可以解决这个问题:
if ($Project.Features -ne $null)
{
$Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" }
}
或
$Project.Features | Where-Object {$_ -ne $null) | Foreach-Object {
Write-Host "Feature name: $($_.Name)"
}
或
$Project.Features | Foreach-Object {
if ($_ -ne $null) {
Write-Host "Feature name: $($_.Name)" }
}
}
但实际上我并不喜欢这些方法中的任何一种,但您认为最佳方法是什么?
答案 0 :(得分:26)
我不认为任何人都喜欢“foreach($ a in $ null){}”和“$ null | foreach-object {}”迭代一次的事实。不幸的是,除了你演示的方式之外别无他法。你可能会更精辟:
$null | ?{$_} | % { ... }
?{$_}
是where-object {$_ -ne $null}
的简写,因为$null
被评估为布尔表达式将被视为$false
我在我的个人资料中定义了一个过滤器,如下所示:
filter Skip-Null { $_|?{ $_ } }
用法:
$null | skip-null | foreach { ... }
过滤器与函数相同,但默认块为process {} not end {}。
更新:从PowerShell 3.0开始,$null
不再可作为集合进行迭代。耶!
-Oisin
答案 1 :(得分:12)
如果你可以修改你的函数,让它返回一个空的集合/数组而不是$ null:
PS> function Empty { $null }
PS> Empty | %{'hi'}
hi
PS> function Empty { @() }
PS> Empty | %{'hi'}
否则,请考虑Oisin的建议,尽管我会建议稍微调整一下:
filter Skip-Null { $_|?{ $_ -ne $null } }
否则,这也会过滤0
和$false
。
2012年4月30日更新:PowerShell v3中已修复此问题。 V3不会迭代标量$ null值。
答案 2 :(得分:2)
快速记录基思完成它的答案
就个人而言,我会返回 nothing 。这很有道理:
PS> function Empty { if ('a' -eq 'b') { 'equal' } }
PS> Empty | % { write-host result is $_ }
但是,如果您将Empty
的结果分配给变量,那么现在您遇到了问题:
PS> $v = Empty
PS> $v | % { write-host result is $_ }
有一个小技巧可以让它发挥作用。只需将Empty
的结果包装为如下数组:
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
答案 3 :(得分:2)
另一种可能性:
$objects | Foreach-Object -Begin{If($_ -eq $null){continue}} -Process {do your stuff here}
中的更多信息