PowerShell -is 运算符在 ForEach-Object 中使用时始终匹配 PSCustomObject
PowerShell -is operator always matching PSCustomObject when used in ForEach-Object
在 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
谁能解释一下这里发生了什么?
PetSerAl,正如他经常做的那样,在评论中提供了关键指针:
将对象通过管道传送到 ForEach-Object
会将它们包装在 [psobject]
实例中(如 $_
/ $PSItem
中所反映),这会导致 -is [pscustomobject]
/ -is [psobject]
到 return $True
对于 any 输入对象 ,因为 - 令人困惑 - [pscustomobject]
是与 [psobject]
相同:它们都是 [System.Management.Automation.PSObject]
的类型加速器 - 与人们的预期相反,[pscustomobject]
是 而不是 [=23= 的缩写].
因此,测试输入对象是否是 [System.Management.Automation.PSCustomObject]
的实例而不是 [pscustomobject]
:
$a | ForEach-Object {
$_ -is [System.Management.Automation.PSCustomObject]
}
请注意,如果您使用 foreach
循环 ,即使 -is [pscustomobject]
也可以工作,因为被枚举的对象 不是 包装在一个额外的 [psobject]
实例中:
foreach ($element in $a) {
$element -is [pscustomobject]
}
这行得通,因为即使是真正的 [System.Management.Automation.PSCustomObject]
技术上 也是幕后的 [System.Management.Automation.PSObject]
。
在 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
谁能解释一下这里发生了什么?
PetSerAl,正如他经常做的那样,在评论中提供了关键指针:
将对象通过管道传送到 ForEach-Object
会将它们包装在 [psobject]
实例中(如 $_
/ $PSItem
中所反映),这会导致 -is [pscustomobject]
/ -is [psobject]
到 return $True
对于 any 输入对象 ,因为 - 令人困惑 - [pscustomobject]
是与 [psobject]
相同:它们都是 [System.Management.Automation.PSObject]
的类型加速器 - 与人们的预期相反,[pscustomobject]
是 而不是 [=23= 的缩写].
因此,测试输入对象是否是 [System.Management.Automation.PSCustomObject]
的实例而不是 [pscustomobject]
:
$a | ForEach-Object {
$_ -is [System.Management.Automation.PSCustomObject]
}
请注意,如果您使用 foreach
循环 ,即使 -is [pscustomobject]
也可以工作,因为被枚举的对象 不是 包装在一个额外的 [psobject]
实例中:
foreach ($element in $a) {
$element -is [pscustomobject]
}
这行得通,因为即使是真正的 [System.Management.Automation.PSCustomObject]
技术上 也是幕后的 [System.Management.Automation.PSObject]
。