测试PSCustomObject的属性时,为什么操作数的顺序很重要

时间:2018-09-03 15:17:51

标签: powershell syntax operators

我在if语句中尝试了$psCustomObject.x -eq $null$null -eq $psCustomObject.x这两种情况,只有后者通过了if。 为什么这样表现呢?似乎不合逻辑。

我的特定用例是一个json文件,其中包含多个环境的配置。环境的名称是对象中的关键,我的目标是在目标不存在的环境(可能是拼写错误)时通知用户,然后停止。

我不想使用! opreator,因为它具有极高的信息与代码比率-很容易忽略,但是却有很大的不同,因此,我通常不喜欢它。它还需要了解语言的工作原理(powershell不是静态类型的,我不希望读者需要了解什么是真理还是不真理)。这听起来可能很愚蠢,但是powershell不是我的主要语言,也不是我的同事的语言。可读性是我的关键因素。

1 个答案:

答案 0 :(得分:3)

tl; dr

要使用$null-eq-ne进行比较,请始终使$null为LHS

$null -eq $psCustomObject.x  # NOT $psCustomObject.x -eq $null
  • 操作数的顺序很重要,因为PowerShell中的比较运算符用作具有 array-valued LHS值的 filters

  • 此外,即使与$null以外的其他内容进行比较,由于隐式类型转换,操作数的顺序也可能很重要。


PowerShell的comparison operators, such as -eq在设计上与数组值 LHS 的行为不同,因此重要的操作数放置在对于通常可交换的运算符
-eq-ne

  • 使用标量 LHS (单个值),比较运算符返回布尔值 ({$True$False表示比较结果。

    • 不过,正如Jeff Zeitlin所指出的,即使标量操作数的放置也很重要 ,即,不同类型的操作数:通常,RHS操作数在比较之前被强制为LHS的数据类型;例如,' 2 ' -eq 2执行 string 比较(将整数2强制转换为字符串'2'),因此返回$False,而2 -eq ' 2 '执行< em>整数比较(将字符串' 2 '转换为[int]),因此返回$True
  • 具有 数组值的LHS (是集合的LHS值),比较运算符返回数组 [object[]]),因为它用作过滤器 :运算符分别应用于输入数组的元素 ,返回的是操作为其返回$True的那些元素的子数组

请注意,从Windows PowerShell v5.1 / PowerShell Core 6.1.0开始,PowerShell仅支持将数组值操作数用作 LHS 操作数; RHS操作数必须为<标量> 或被强制为1。 [1]


因此,在您的示例中, $null -eq $psCustomObject.x$psCustomObject.x -eq $null不可互换的,并测试不同的条件

# Is the RHS $null?
# Whether the concrete RHS value is then a scalar or an array doesn't matter.
$null -eq $psCustomObject.x

# * If $psCustomObject.x is a scalar: is that scalar $null?
# * If $psCustomObject.x is an ARRAY: 
#   RETURN THE SUB-ARRAY OF ELEMENTS THAT ARE $null
$psCustomObject.x -eq $null

在布尔上下文中(例如在if语句中)使用 时,数组,例如以数组值的LHS返回的数组,评估如下PetSerAl求助的帽子提示。

  • 数组或包含空数组的 1-element数组的值为$False
  • 包含标量的 1元素数组计算得出该标量的(隐含)布尔值,例如[bool] @(0)[bool] 0实际上相同,即, $False
  • 2+元素数组或包含非空数组的 1-element数组总是 $True ,而不考虑其元素的值(例如,
    [bool] ($False, $False)[bool] (, (, $False))均为$True

注意:术语 array 在上面使用得比较宽松。严格来说,以上内容适用于实现[System.Collections.IList]接口的任何类型的实例-请参见the source code
除了数组之外,还包括[System.Collections.ArrayList][System.Collections.Generic.List[<type>]]之类的类型。


示例:两个比较在布尔上下文中的评估结果不同:

注意:

  • 这个例子有些人为-请告诉我们是否有更好的例子。
    运算符-ne可以提供更简单的示例。

  • 我无法为您描述的特定行为提供一个示例,其中$null -eq $psCustomObject.x返回$True,而$psCustomObject.x -eq $null却没有。如果确实如此,请告诉我们具体的.x值。

# Construct a custom object with an array-valued .x property that
# contains at least 2 $null values.
$psCustomObject = [pscustomobject] @{ x = @(1, $null, 2, $null) }

# $False, as expected: the value of .x is an array, and therefore not $null
[bool] ($null -eq $psCustomObject.x) 

# !! $True, because because 2 elements in the input array (.x)
# !! are $null, so a 2-element array - ($null, $null) - is returned, which in a
# !! Boolean context is always $True.
[bool] ($psCustomObject.x -eq $null) 

[1]在文档中,-replace与比较运算符组合在一起,从技术上讲,其RHS是一个数组,但是此数组的元素本质上是标量操作数:要匹配的正则表达式,以及替换字符串。