如何在管道中处理$ null

Ser*_*ver 19 powershell

我的PowerShell代码中经常出现以下情况:我有一个返回对象集合的函数或属性,或者$null.如果将结果推送到管道中,则还要处理管道中的元素,如果$null它是唯一的元素.

例:

$Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" }
Run Code Online (Sandbox Code Playgroud)

如果没有功能($ Project.Features返回$ null),您将看到一行"功能名称:".

我看到三种解决方法:

if ($Project.Features -ne $null)
{
  $Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" }
}
Run Code Online (Sandbox Code Playgroud)

要么

$Project.Features | Where-Object {$_ -ne $null) | Foreach-Object { 
  Write-Host "Feature name: $($_.Name)" 
}
Run Code Online (Sandbox Code Playgroud)

要么

$Project.Features | Foreach-Object { 
  if ($_ -ne $null) {
    Write-Host "Feature name: $($_.Name)" }
  }
}
Run Code Online (Sandbox Code Playgroud)

但实际上我并不喜欢这些方法中的任何一种,但你认为最好的方法是什么?

x0n*_*x0n 26

我认为没有喜欢"foreach($ a in $ null){}"和"$ null | foreach-object {}"迭代一次的事实.不幸的是,除了你演示的方式之外别无他法.你可能会更精辟:

$null | ?{$_} | % { ... }
Run Code Online (Sandbox Code Playgroud)

?{$_}是用于速记where-object {$_ -ne $null}作为$null评价为布尔表达式将作为被处理$false

我的个人资料中定义了一个过滤器,如下所示:

filter Skip-Null { $_|?{ $_ } }
Run Code Online (Sandbox Code Playgroud)

用法:

$null | skip-null | foreach { ... }
Run Code Online (Sandbox Code Playgroud)

过滤器与函数相同,但默认块为process {} not end {}.

更新:从PowerShell 3.0开始,$null不再可以作为集合进行迭代.好极了!

-Oisin

  • 简洁速记的问题在于它会拒绝任何强制为"false"的东西,其中包括诸如`0`,`"",`@()`,`@(0)`之类的东西,......我d可能期望`Skip-Null`实际上只跳过`$ null`.我知道在这个问题的上下文中结果是一样的,但是对于可能在其他地方使用的过滤器来说...... (5认同)

Kei*_*ill 12

如果你可以修改你的函数,让它返回一个空的集合/数组而不是$ null:

PS> function Empty { $null }
PS> Empty | %{'hi'}
hi

PS> function Empty { @() }
PS> Empty | %{'hi'}
Run Code Online (Sandbox Code Playgroud)

否则,请考虑Oisin的建议,尽管我建议稍微调整一下:

filter Skip-Null { $_|?{ $_ -ne $null } } 
Run Code Online (Sandbox Code Playgroud)

否则这也将过滤0$false.

更新4-30-2012: PowerShell v3中已修复此问题.V3不会迭代标量$ null值.

  • 对于这个问题,这在v3或v4中是不固定的.他们只把它固定在foreach上,而不是用于管道.请参阅http://blogs.msdn.com/b/powershell/archive/2012/06/14/new-v3-language-features.aspx (5认同)