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

Как проверить массив $null в PowerShell

Я использую переменную массива в 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?

4b9b3361

Ответ 1

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

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

$foo.count -gt 0

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

Ответ 2

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

$null -eq $foo

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

Ответ 3

if($foo -eq $null) { "yes" } else { "no" }

help about_comparison_operators 

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

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

Ответ 4

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

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

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

Ответ 5

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

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

[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

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

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

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

Ответ 6

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

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 метод 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