Как проверить массив $ null в PowerShell - PullRequest
44 голосов
/ 25 февраля 2011

Я использую переменную-массив в PowerShell 2.0.Если у него нет значения, это будет $ null, который я могу успешно проверить:

PS C:\> [array]$foo = $null
PS C:\> $foo -eq $null
True

Но когда я даю ему значение, проверка $ null ничего не возвращает:

PS C:\> [array]$foo = @("bar")
PS C:\> $foo -eq $null
PS C:\>

Как "-eq $ null" не дает результатов?Это либо $ null, либо нет.

Как правильно определить, заполнен ли массив, по сравнению с $ null?

Ответы [ 6 ]

68 голосов
/ 25 февраля 2011

Это массив, так что вы ищете Count для проверки содержимого.

Я бы порекомендовал

$foo.count -gt 0

«Почему» это связано с тем, как PSH обрабатывает сравнение объектов коллекции

38 голосов
/ 26 февраля 2011

Вы можете изменить порядок операндов:

$null -eq $foo

Обратите внимание, что -eq в PowerShell не является отношением эквивалентности.

20 голосов
/ 25 февраля 2011
if($foo -eq $null) { "yes" } else { "no" }

help about_comparison_operators 

отображает справку и включает этот текст:

Все операторы сравнения, кроме операторов включения (-contains, -notcontains) и операторов типа (-is, -isnot), возвращают логическое значениекогда входные данные для оператора (значение в левой части оператора) представляют собой одно значение (скаляр). Когда входные данные представляют собой набор значений , операторы включения и операторы типа возвращают любые совпадающие значения.Если в коллекции нет совпадений, эти операторы ничего не возвращают.Операторы включения и операторы типа всегда возвращают логическое значение.

8 голосов
/ 07 августа 2013

Если ваше решение требует возврата 0 вместо true / false, я считаю это полезным:

PS C:\> [array]$foo = $null
PS C:\> ($foo | Measure-Object).Count
0

Эта операция отличается от свойства count массива, поскольку Measure-Objectподсчет предметов.Так как их нет, он вернет 0.

3 голосов
/ 17 марта 2017

Как вы хотите, чтобы вещи вели себя?

Если вы хотите, чтобы массивы без элементов обрабатывались так же, как и неназначенные массивы, используйте:

[array]$foo = @() #example where we'd want TRUE to be returned
@($foo).Count -eq 0

Если вы хотите, чтобы пустой массив рассматривался как имеющий значение (хотя и пустое), используйте:

[array]$foo = @() #example where we'd want FALSE to be returned
$foo.PSObject -eq $null

Если вы хотите, чтобы массив, заполненный только нулевыми значениями, обрабатывался как нулевой:

[array]$foo = $null,$null
@($foo | ?{$_.PSObject}).Count -eq 0 

Примечание: в приведенном выше примере я использую $_.PSObject над $_, чтобы избежать фильтрации [bool]$false, [int]0, [string]'' и т. Д .; так как здесь мы сосредоточены исключительно на нулях.

1 голос
/ 22 декабря 2018

Другие ответы обращаются к основному вопросу вопроса, но только чтобы прокомментировать эту часть ...

PS C:\> [array]$foo = @("bar")
PS C:\> $foo -eq $null
PS C:\>

Как "-eq $ null" может не дать результатов? Это либо $ null, либо нет.

Поначалу это сбивает с толку, но означает , что дает результат $foo -eq $null, просто результат не имеет отображаемого представления.

Поскольку $foo содержит массив, $foo -eq $null означает «вернуть массив, содержащий элементы $foo, равные $null». Есть ли элементы $foo, которые равны $null? Нет, поэтому $foo -eq $null должен возвращать пустой массив. Это именно то, что он делает, проблема в том, что когда на консоли отображается пустой массив, вы видите ... ничего ...

PS> @()
PS> 

Массив все еще там, даже если вы не видите его элементы ...

PS> @().GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> @().Length
0

Мы можем использовать аналогичные команды, чтобы подтвердить, что $foo -eq $null означает , возвращая массив, который мы не можем «увидеть» ...

PS> $foo -eq $null
PS> ($foo -eq $null).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> ($foo -eq $null).Length
0
PS> ($foo -eq $null).GetValue(0)
Exception calling "GetValue" with "1" argument(s): "Index was outside the bounds of the array."
At line:1 char:1
+ ($foo -eq $null).GetValue(0)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : IndexOutOfRangeException

Обратите внимание, что я вызываю метод Array.GetValue вместо использования индексатора (то есть ($foo -eq $null)[0]), поскольку последний возвращает $null для недопустимых индексов, и нет никакого способа отличить их от действительного индекс, который содержит $null.

Мы видим похожее поведение, если мы проверяем $null в / против массива, который содержит $null элементов ...

PS> $bar = @($null)
PS> $bar -eq $null
PS> ($bar -eq $null).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> ($bar -eq $null).Length
1
PS> ($bar -eq $null).GetValue(0)
PS> $null -eq ($bar -eq $null).GetValue(0)
True
PS> ($bar -eq $null).GetValue(0) -eq $null
True
PS> ($bar -eq $null).GetValue(1)
Exception calling "GetValue" with "1" argument(s): "Index was outside the bounds of the array."
At line:1 char:1
+ ($bar -eq $null).GetValue(1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : IndexOutOfRangeException

В этом случае $bar -eq $null возвращает массив, содержащий один элемент, $null, который не имеет визуального представления на консоли ...

PS> @($null)
PS> @($null).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS> @($null).Length
1
...