Подтвердить что ты не робот

Как обрабатывать $null в конвейере

В моем коде 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)" }
  }
}

Но на самом деле мне не нравится какой-либо из этих подходов, но что вы видите как лучший подход?

4b9b3361

Ответ 1

Мне не кажется, что кому-то нравится тот факт, что и "foreach ($ a в $null) {}" и "$ null\foreach-object {}" повторяются один раз. К сожалению, нет другого способа сделать это, чем способы, которые вы продемонстрировали. Вы можете быть более точными:

$null | ?{$_} | % { ... }

?{$_} является сокращением для where-object {$_ -ne $null}, поскольку $null, оцененное как булево выражение, будет рассматриваться как $false

У меня есть фильтр, определенный в моем профиле:

filter Skip-Null { $_|?{ $_ } }

Использование:

$null | skip-null | foreach { ... }

Фильтр такой же, как и функция, кроме блока по умолчанию - процесс {} not end {}.

ОБНОВЛЕНИЕ. Начиная с версии PowerShell 3.0, $null уже не является итерируемым как коллекция. Ура!

-Oisin

Ответ 2

Если вы можете изменить свою функцию, верните пустую коллекцию/массив вместо $null:

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

PS> function Empty { @() }
PS> Empty | %{'hi'}

В противном случае перейдите к тому, что предлагает Oisin, хотя я бы предложил небольшой настрой:

filter Skip-Null { $_|?{ $_ -ne $null } } 

В противном случае это также будет фильтровать 0 и $false.

Обновление 4-30-2012: Эта проблема исправлена ​​в PowerShell v3. V3 не будет перебирать скалярное значение $null.

Ответ 3

Быстрая заметка Кейту, чтобы ответить на него.

Лично я ничего не вернул бы. Это имеет смысл:

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

Ответ 4

Другая возможность:

$objects | Foreach-Object -Begin{If($_ -eq $null){continue}} -Process {do your stuff here}

Дополнительная информация в about_Continue