【问题标题】:How to test for $null array in PowerShell如何在 PowerShell 中测试 $null 数组
【发布时间】:2011-07-03 22:50:25
【问题描述】:

我在 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 的正确方法是什么?

【问题讨论】:

    标签: powershell null


    【解决方案1】:

    这是一个数组,因此您正在寻找 Count 来测试内容。

    我会推荐

    $foo.count -gt 0
    

    其中的“为什么”与 PSH 如何处理集合对象的比较有关

    【讨论】:

    • 不幸的是,[array]$foo = $null 时不起作用。 $foo.count 不返回 0 而不是 0。
    • 但是 (nothing -gt 0 == FALSE),这就是我建议使用该运算符的原因。如果您检查是否有真/假,则无论是否为空
    • 啊,我明白了。是的,这比必须使用 if ($foo -eq $null) 语句的 else 块更短且更直观。有趣的是,当[array]$foo = $null$foo.count -eq 0 为 False 时,$foo.count -lt 0 为 True。我猜 $null 小于 0。想知道这是否记录在某处?
    • 如果你真的想伤脑筋,powershell 会告诉你 $null -lt 0 == TRUE,但 $null -lt -1 == FALSE。所以 -1
    • 如果您有 Set-StrictMode -Version Latest,此方法将失败
    【解决方案2】:

    您可以重新排序操作数:

    $null -eq $foo
    

    请注意,PowerShell 中的-eq 不是等价关系。

    【讨论】:

    • 酷。没想到。因此 -eq 仅在集合位于 -eq 的 left 的情况下扫描集合的值。
    • @Mark:确实。请参阅help about_Comparison_Operators,其中对此进行了描述。
    • 感谢@Joey 的解决方案,即使在数组只有一个值或没有值的情况下也能正常工作!
    【解决方案3】:
    if($foo -eq $null) { "yes" } else { "no" }
    
    help about_comparison_operators 
    

    显示帮助并包含以下文本:

    所有比较运算符,除了 包含运算符(-contains, -notcontains) 和类型运算符 (-is, -isnot) 在输入到运算符(值 在运算符的左侧)是 单个值(标量)。 当 输入是值的集合, 包含运算符和类型 运算符返回任何匹配的值。 如果没有匹配项 集合,这些运算符不 返回任何东西。遏制 运算符和类型运算符总是 返回一个布尔值。

    【讨论】:

    • 是的,我错过了 -eq 扫描非空集合以查找匹配值并返回 VALUE 的想法,而不是 True 或 False。非常令人困惑,特别是如果集合包含空字符串。如果[array]$foo=@(""),您的 if 语句有效,但它的逆语句无效:if($foo -ne $null) { "no" } else { "yes" } 返回“是”。由于我要做的主要事情是测试 NOT null(即有一些元素需要处理),这意味着我必须使用 if($foo -eq $null) { # Do nothing } else { #Do something }
    • 谢谢。我试图弄清楚为什么这似乎没有答案:$a = @(); $a -eq $null
    • 在 PowerShell 中,$null 应该在比较的左侧。
    【解决方案4】:

    如果您的解决方案需要返回 0 而不是真/假,我发现这很有用:

    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
      

      如果您希望将仅填充空值的数组视为空值:

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

      注意:在上面我使用$_.PSObject而不是$_来避免[bool]$false[int]0[string]''等被过滤掉;因为这里我们只关注空值。

      【讨论】:

      • 这些是关于如何为各种行为初始化数组的有用想法,但这并不能回答最初的问题,“确定数组是否填充与 $null 的正确方法是什么?”也许应该修改添加,“即使我不知道数组是如何初始化的?”
      【解决方案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 method,而不是使用索引器(即($foo -eq $null)[0]),因为后者为无效索引返回$null,并且无法将它们与恰好包含@987654338 的有效索引区分开来@。

      如果我们在包含$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
      

      【讨论】:

      • 哇。谢谢你的解释!
      • 我用它对 Pester 做了类似的事情: # 如果变量是空数组。 $value = @() $value.GetType().BaseType.ToString() |应该 -Be 'System.Array' # 如果变量是 $null。 $value = $null { $value.GetType().BaseType.ToString() } |应该扔
      【解决方案7】:

      注意开关。它永远不会运行空数组,例如作为空目录的输出。

      switch ( $null ) { default { 'yes' } }
      yes
      
      switch ( @() ) { default { 'yes' } }  # no output
      
      mkdir foo
      switch ( dir foo ) { default { 'yes' } }  # no output
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 2020-06-08
        • 1970-01-01
        相关资源
        最近更新 更多