Ответ 1
Его массив, поэтому вы ищете Count для проверки содержимого.
Я бы рекомендовал
$foo.count -gt 0
"Почему" относится к тому, как PSH обрабатывает сравнение объектов коллекции
Я использую переменную массива в 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?
Его массив, поэтому вы ищете Count для проверки содержимого.
Я бы рекомендовал
$foo.count -gt 0
"Почему" относится к тому, как PSH обрабатывает сравнение объектов коллекции
Вы можете изменить порядок операндов:
$null -eq $foo
Обратите внимание, что -eq
в PowerShell не является отношением эквивалентности.
if($foo -eq $null) { "yes" } else { "no" }
help about_comparison_operators
отображает справку и включает этот текст:
Все операторы сравнения, кроме операторы сдерживания (-контейнеры, -notcontains) и операторы типов (-is, -isnot) возвращают логическое значение при вводе в оператор (значение в левой части оператора) является одно значение (скаляр). Когда input - это набор значений, операторов локализации и типа операторы возвращают любые соответствующие значения. Если совпадений нет в коллекции, эти операторы не вернуть что-нибудь. Сдерживание операторы и операторы типов всегда возвращает логическое значение.
Если ваше решение требует вернуть 0 вместо true/false, я нашел, что это полезно:
PS C:\> [array]$foo = $null
PS C:\> ($foo | Measure-Object).Count
0
Эта операция отличается от свойства count массива, потому что Measure-Object
подсчитывает объекты. Поскольку их нет, он вернет 0.
Как вы хотите, чтобы вещи вели себя?
Если вы хотите, чтобы массивы без элементов обрабатывались так же, как непризнанные массивы, используйте:
[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]''
и т.д.; поскольку здесь мы сосредоточены исключительно на нулях.
Другие ответы обращены к основной теме вопроса, но только чтобы прокомментировать эту часть...
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