在ForEach-Object中使用PowerShell -is运算符时始终匹配PSCustomObject

时间:2018-11-12 18:55:22

标签: powershell powershell-v6.0

在Mac上使用PowerShell Core 6.1。看来,将数组传递给ForEach-Object会修改或包装每个元素,以便-is运算符将其全部视为PSCustomObjects。

让我演示一下:

设置一个由四个不同类型的项组成的数组(使用JSON,因为在我的实际用例中数据就是从那里来的):

$a = '[4, "Hi", {}, true]' | ConvertFrom-Json

按索引迭代列表,并确定哪些是PSCustomObjects:

0..3 | ForEach-Object { 
    $v = $a[$_]
    $t = $v.GetType().FullName
    $is = $v -is [PSCustomObject]
    "$t - $is"
}

(对我而言)输出正是我所期望的:

System.Int64 - False
System.String - False
System.Management.Automation.PSCustomObject - True
System.Boolean - False

但是如果我只是将数组通过管道传递给ForEach-Object:

$a | ForEach-Object { 
    $v = $_
    $t = $v.GetType().FullName
    $is = $v -is [PSCustomObject]
    "$t - $is"
}

现在输出声称这四个都是PSCustomObjects

System.Int64 - True
System.String - True
System.Management.Automation.PSCustomObject - True
System.Boolean - True

有人可以解释这里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

PetSerAl,就像他经常做的那样,在评论中提供了关键的指针:

将对象管道输送到ForEach-Object会将它们包装在[psobject]实例中,这将导致-is [pscustomobject] / -is [psobject]返回<{> 1 输入对象,因为-令人困惑-$True[pscustomobject]相同:它们都是[psobject]的类型加速器-违反了人们的期望,{ {1}}不是[System.Management.Automation.PSObject]的缩写。

因此,测试输入对象是否为[pscustomobject] 而不是[System.Management.Automation.PSCustomObject]的实例:

[System.Management.Automation.PSCustomObject]

请注意,如果您使用[pscustomobject] 循环,即使$a | ForEach-Object { $_ -is [System.Management.Automation.PSCustomObject] } 也可以使用,因为要枚举的对象然后 not 包裹在额外的foreach实例:

-is [pscustomobject]

之所以可行,是因为即使在技术上,甚至善意的[psobject]也是幕后的foreach ($element in $a) { $element -is [pscustomobject] }