【问题标题】:What operator should be used to detect an empty psobject?应该使用什么运算符来检测空的 psobject?
【发布时间】:2018-11-06 23:11:37
【问题描述】:

使用以下示例:

$test = '{ }' | ConvertFrom-Json

如何检测 $test 为空?

不起作用:

$test -eq $null
-not $test

这确实有效,但感觉不对:

$test.ToString() -eq ''

这是一个简化的示例,但我的用例是我使用 invoke-rest 方法从 REST api 获得的响应,某些属性返回为空 psobjects。

【问题讨论】:

  • 怎么样:If ($test -eq "") {Write-Host "It's empty!"} ELSE {Write-Host "It's not empty!"}

标签: powershell


【解决方案1】:

通过其字符串表示来测试空(无属性)自定义对象([pscustomobject])的最简单解决方案 ,但是你需要使用一个可扩展的字符串(字符串插值,"..."而不是.ToString()来获得它:

# Returns $True, if custom object $test is empty, i.e. has no properties
-not "$test"

注意:-not $test.ToString()应该是等价的,但目前(从 PowerShell Core 6.1 开始)不是,因为bug。由于存在错误,any [pscustomobject] 实例返回 空字符串 from.ToString()
另一种解决方法是使用.psobject.ToString()

只有一个空(无属性)自定义对象字符串化为可扩展字符串内的 空字符串,并且在 PowerShell 中将一个空字符串强制转换为布尔值会产生 $False,而任何非空字符串都会产生$True.

另一种方法是与空字符串进行比较作为 LHS,这会隐式强制 RHS 上的 [pscustomobject] 被字符串化:

# NOTE: Works ONLY with '' on the LHS.
'' -eq $test

概念上更清晰的方法,虽然它依赖于隐藏的.psobject 属性 PowerShell 添加到所有对象,包含反射信息:

0 -eq @($test.psobject.Properties).Count

请注意需要使用@(...) 来强制枚举属性,以便对其进行计数 - 请参阅下一节。

上述方法很方便,但如果$test 是一个具有许多属性的大型对象,它可能会很昂贵——尽管从绝对意义上讲,这在实践中可能并不重要。


一个更便宜但更模糊的解决方案是访问.psobject.Properties集合而不枚举其所有成员

# Returns $true, if $test has no properties
-not $test.psobject.Properties.GetEnumerator().MoveNext()

.psobject.Properties 集合显然是惰性枚举的,因此没有 .Count 属性;因此,使用 .GetEnumerator().MoveNext() 是一种将枚举限制在 first 属性(如果有)的方法。


至于你尝试了什么

$test -eq $null

$test 仍然是一个对象,即使它碰巧没有属性,而且根据定义,一个对象绝不是$null

-not $test

PowerShell 的隐式到布尔转换将 any [pscustomobject] 实例视为$True,无论它是否恰好具有属性;例如,[bool] ([pscustomobject] @{}) 产生 $True

要了解如何将其他数据类型强制转换为布尔值,请参阅this answer

【讨论】:

    【解决方案2】:

    可能更贵,但不那么晦涩;正在使用原生的Get-Member cmdlet:

    [Bool]($Test | Get-Member -MemberType NoteProperty)
    

    注意$Test不应该是$Null(而不是一个空对象)否则会产生错误(就像在$Null上使用方法一样)。为避免这种情况,您还可以考虑使用:

    $Test -and ($Test | Get-Member -MemberType NoteProperty)
    

    【讨论】:

    • 正如您所说,并不便宜,但概念上更清晰(+1)。您可以通过将-ErrorAction Ignore 添加到Get-Member 调用中更简洁地避免$null 问题:[Bool]($Test | Get-Member -ErrorAction Ignore -MemberType NoteProperty),或者作为单个命令:[bool] (Get-Member -InputObject $Test -MemberType NoteProperty -ErrorAction Ignore)
    【解决方案3】:

    使用字符串测试并在比较的 右侧 使用 $Var 进行测试,以便将其强制转换为左侧的类型。您还可以使用下面的[string] 方法进行测试... [grin]

    $Test = '{ }' | ConvertFrom-Json
    
    $Test -eq $Null
    $Null -eq $Test
    $Test -eq ''
    ''
    '' -eq $Test
    [string]::IsNullOrEmpty($Test)
    [string]::IsNullOrWhiteSpace($Test)
    

    输出...

    False
    False
    False
    
    True
    True
    True
    

    【讨论】:

      【解决方案4】:

      这对我有用...

      if ((ConvertTo-Json -Depth 1 $testObj) -eq (ConvertTo-Json @{})) {
          echo 'empty object'
      }
      

      【讨论】:

        猜你喜欢
        • 2014-08-02
        • 2012-08-19
        • 1970-01-01
        • 2011-08-08
        • 2020-01-24
        • 2016-01-05
        • 2022-01-19
        • 1970-01-01
        • 2021-12-17
        相关资源
        最近更新 更多