当前位置: 首页 > 知识库问答 >
问题:

为什么PowerShell比较运算符不枚举大小为1的集合?

陶高峯
2023-03-14

在检查变量和变量集合是否为空时,比较运算符似乎会枚举大小为2或更大的集合:

> if ( @( $null, $null ) -eq $null ) { $True } else { $False }
True

但它们不适用于1号收藏:

> if ( @( $null ) -eq $null ) { $True } else { $False }
False

我知道使用左侧(< code>$null -eq @( $null ))进行空比较是最佳实践,但是有人能解释一下这里发生了什么吗?我怀疑有更微妙的事情发生,影响我写的其他代码。

为什么这两个结果不一样?

共有2个答案

连昊天
2023-03-14

以下项目的计算结果为< code>$false:

@()
0
$null
$false
''

在你的第一个例子中:

@($null, $null) -eq $null

这计算为<code>$null,$null

[bool]($null, $null)

在您的第二个示例中,您观察到的是像第一个示例一样过滤数组,但是< s >返回一个标量(而不是一个数组),因为数组中只有一项与过滤器匹配:

@($null) -eq $null

这计算结果为<code>@($null),如下所示:

[bool]@($null)

脚注:在powershell v2中,有一个关于< code>$null过滤的错误,它产生了左侧的< code>$null比较。此错误导致完全跳过< code>if/else块。

干浩阔
2023-03-14

tl;博士

在PowerShell条件/隐式布尔上下文中:

>

  • 单元素数组被视为标量:也就是说,它们的唯一元素本身被解释为布尔值

    2元素数组始终是$true,无论其内容如何。

    使用数组作为 LHS 时,数组感知运算符(如 -eq)也总是输出数组。

    由于数组元素都是$null并且与$null进行比较,因此比较是有效的无运算-例如,@($null)-eq$null会导致@(null)-并且您的条件等价于:

    [bool] @( $null, $null ) # -> $true - array with 2+ elements is always $True
    [bool] @( $null )        # -> $false(!) - treated like: [bool] $null
    

    也许令人惊讶的是,隐式布尔逻辑将管道逻辑应用于数组:

    也就是说,单个元素数组(概念上)被展开,其元素被解释为布尔值。

    因此,[bool]@($null)被视为与[bool]$null,即$false

    一般来说,@(

    相比之下,如果数组有 2 个或更多元素,则它始终$true布尔上下文中,即使其所有元素都单独被视为$false

    测试任意数组是否为空的解决方法:

    将您的条件基于。计数属性:

    if ( (<array>).Count ) { $true } else { $false }
    

    您可以将-gt 0,但这并不是严格必要的,因为任何非零值都隐含在$true中。

    应用于您的示例:

    PS> if ( ( @($null) -eq $null ).Count ) { $true } else { $false }
    True
    

    测试任意值是否为(标量)< code>$null:

    if ($null -eq <value>) { $true } else { $false }
    

    注意$null必须用作LHS以防止数组过滤逻辑生效,应该

    这也是为什么带有PowerShell扩展的Visual Studio代码建议在编写类似于< code>$var -eq $null的代码时“$null应该在比较的左边”的原因。

    [1]到布尔转换摘要:

    > < li >在标量中: < ul > < li>

    下面是隐式的< code>$false:

    >

  • “”/“”(空字符串)

    0(任何数字类型)。

    $null

    >

  • 陷阱:将$null与显式使用-eq的布尔值进行比较总是$false,即使将$null作为RHS(尽管RHS通常被强制为LHS的类型):

    $false -eq $null # !! $false - unlike `$false -eq [bool] $null`
    

    陷阱:任何非空字符串的计算结果均为$true

    > < li>

    例如,< code>[bool] 'False'是< code>$true

    请注意,这与显式字符串解析不同:[bool]::Parse('false')确实返回$false(对于'true'$true则返回,但不识别其他内容)。

    任何其他(非集合)类型的实例都隐式$true,包括类型 [伪对象][哈希表](PowerShell 将其视为单个对象,而不是条目集合)。

    • 不幸的是,这包括定义显式[bool].NET转换运算符的类型,这意味着这些运算符-大部分-不受尊重;看看这个答案

    >

  • 在数组等集合中(更准确地说,是实现 IList 接口的类似集合的类型 - 请参阅源代码):
    • 空集合始终$false,指示缺少命令输出的特殊“空集合”值也是如此,[系统.管理.自动化.内部.自动化取消]::值

      陷阱:单元素集合评估为:

        < li >如果唯一的元素是标量:它的布尔值 < li >如果该元素本身是一个集合:< code>$true如果它至少有一个元素(不管该元素是什么)。

      2元素集合总是$true

  •  类似资料:
    • 虽然JavaScript的类型严格比较运算符(,)很好,但它没有相应的大于/小于的严格比较。 为什么不呢?我问这个问题完全是希望答案是“嗯,因为它没有”,但我还是在问,以防遗漏这些运营商有一个有趣和/或令人沮丧的历史原因。

    • 因为枚举成员不是有序的,所以它们只支持通过标识(identity) 和相等性 (equality) 进行比较。下面来看看 == 和 is 的使用: #!/usr/bin/env python3 # -*- coding: UTF-8 -*- from enum import Enum class User(Enum): Twowater = 98 Liangdianshui

    • 问题内容: 在Swift 3中,如果我使用或,这是一个编译错误 编译错误: 可选类型’Int?’的值 没有包装; 你是说用’!’ 要么 ‘?’? 但如果我与或比较 问题答案: 对于相等运算符来说,支持可选值是很有意义的,因为对于任何整数值变量,这是绝对清楚的: 当且仅当它们的值相同时 另一方面,尚不清楚与的比较应如何起作用: 是小于? 如果我想对数组进行排序以使所有s都在末尾出现,那么我希望小于。

    • 是否有人理解对每个PowerShell的比较运算符进行区分大小写和不区分大小写版本背后的原因?为什么要使默认值不区分大小写? 例如,以-eq和-ceq为例。这些运算符用于比较所有类型,而不仅仅是字符串。那么,0-CEQ1意味着什么呢?如何区分大小写比较两个整数?

    • 问题内容: 我只是意识到,SQL Server比较器用于文本比较时不区分大小写。关于此功能,我有几个问题: 所有数据库都相同还是特定于SQL Server? 到目前为止,我一直在使用该功能来确保文本比较不敏感。遵循相同的方法还是个好主意吗? 如何在SQL Server中进行区分大小写的比较? 为什么操作员默认不区分大小写的比较? 问题答案: 不可以,区分大小写与等号无关。 区分大小写由数据库的排序

    • 实现后缀计算器,需要检查运算符的优先级是否低于另一个运算符。以下是我到目前为止所拥有的: 我尝试了许多不同的方法来检查传入的字符的优先级,但都没有用。有没有简单的方法来比较一个枚举的两个值?我需要创建一个循环吗?