数组访问的奇怪天花板

Jar*_*lec 5 arrays powershell scripting

在使用数组索引器时,我在PowerShell中遇到了奇怪的代码片段.为什么你认为它的行为方式如下?

我期望的标准行为是每次都获得数组的确切成员,在这种情况下首先是零基础

(0, 1)[0] == 0          # as expected
(0, 1 -ne 2)[0] == 0    # as expected regardless second member would be casted from bool to int
(0, 1 -ne 0)[0] == 1    # magic starts here
Run Code Online (Sandbox Code Playgroud)

到目前为止,我希望它的结果是1 -ne 0从bool转换为int,并且在数组的第一个位置与0一起形成一些已知异常但是:

(0, 60 -ne 0)[0] == 60   # ignores first member and whole (-ne 0) part
(0, 60 -ne 1)[0] == 0    # as expected
(1, 60 -ne 0)[0] == 1    # as expected
Run Code Online (Sandbox Code Playgroud)

在这一点上,它似乎只有当第一个成员0不管它作为变量传递而第二部分必须是精确的时才生效1 -ne 0

# doesn't matter if first member is variable    
$x = 0
($x, 1 -ne 0)[0] == 1       # same magic as before
($x, 0 -ne 1)[0] == 0       # as expected by may be caused by leading zero of 0 -ne 1
($x, 0 -ne 0)[0] == null    # this is also very weird
($x, 1 -ne 1)[0] == 0       # maybe return of bool comparison or simply first member, I would expect null as before
Run Code Online (Sandbox Code Playgroud)

我知道所有想知道这些事情都可以通过简单地防止代码在数组中混合bool和int来解决.我是如何发现它在我们用作ceilling的遗留代码中使用的

return ([int]$lastResultCode, 1 -ne 0)
Run Code Online (Sandbox Code Playgroud)

代替:

if ($lastResultCode == 0) return 1
else return $lastResultCode
Run Code Online (Sandbox Code Playgroud)

但是考虑这个代码已经在空中无法更改此代码但在该机器上可能是PowerShell版本升级的情况,因此可能会改变未来的行为.对于这种情况,我想请你就你的行为推动你的意见.

iCo*_*dez 6

这里有两件事:

  1. ,经营者具有比比较符的优先级高.所以,表达式如下:

    (0, 1 -ne 0)[0]
    
    Run Code Online (Sandbox Code Playgroud)

    实际上解析为:

    ((0, 1) -ne 0)[0]
    
    Run Code Online (Sandbox Code Playgroud)

    您可以在下面阅读有关PowerShell运算符优先级的更多信息about_Operator_Precedence.

  2. PowerShell比较运算符可以使用标量(单个项)和数组.当您将它们与数组一起使用时,它们将返回满足条件的所有项:

    PS > (4, 5, 3, 1, 2) -gt 2  # All items greater than 2
    4
    5
    3
    PS > (4, 5, 3, 1, 2) -ne 3  # All items that do not equal 3
    4
    5
    1
    2
    PS >
    
    Run Code Online (Sandbox Code Playgroud)

考虑到这些要点,您可以轻松解释您所看到的行为.表达方式:

(0, 1 -ne 0)[0]
Run Code Online (Sandbox Code Playgroud)

首先被解析为:

((0, 1) -ne 0)[0]
Run Code Online (Sandbox Code Playgroud)

然后变成:

(1)[0]
Run Code Online (Sandbox Code Playgroud)

因为-ne返回的项目(0, 1)不相等0,这只是1.


解决方案只是使用一组额外的括号:

(0, (1 -ne 0))[0]
Run Code Online (Sandbox Code Playgroud)

这将导致PowerShell首先评估该1 -ne 0部件并按预期运行:

PS > (0, (1 -ne 0))
0
True
PS > (0, (1 -ne 0))[0]
0
PS >
Run Code Online (Sandbox Code Playgroud)