Как обработать $ null в конвейере - PullRequest
19 голосов
/ 05 декабря 2010

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

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

Ответы [ 4 ]

26 голосов
/ 05 декабря 2010

Не думаю, что кому-либо нравится тот факт, что и "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 больше не повторяется как коллекция.Ууу!

-оизин

12 голосов
/ 05 декабря 2010

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

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

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

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

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

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

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

2 голосов
/ 18 октября 2011

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

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

Больше информации в about_Continue

2 голосов
/ 06 декабря 2010

Краткое примечание к ответу Кита, чтобы завершить его

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

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...