Powershell 当对象筛选器意外地匹配整个输入集合时,Get Member显示集合类型而不是元素类型

Powershell 当对象筛选器意外地匹配整个输入集合时,Get Member显示集合类型而不是元素类型,powershell,filtering,enumeration,Powershell,Filtering,Enumeration,MyGet-AzureStorSimpleAccessControlRecord调用返回2个对象,带有 Name属性值servertest4和servertest3 但是, Get-AzureStorSimpleAccessControlRecord | where {$_.Name -like '*servertest4*'} 正在意外地返回两个对象 如果我通过for-each循环传递它,where语句将捕获该属性 Get-AzureStorSimpleAccessControlRecord

My
Get-AzureStorSimpleAccessControlRecord调用返回2个对象,带有
Name
属性值
servertest4
servertest3

但是,

Get-AzureStorSimpleAccessControlRecord | where {$_.Name -like '*servertest4*'}
正在意外地返回两个对象

如果我通过for-each循环传递它,where语句将捕获该属性

Get-AzureStorSimpleAccessControlRecord | % {$_.Name} | where {$_ -like 'servertest4'}
servertest4
意外地将原始命令传递给
Get Member
不会显示
Name
属性。这就是问题所在吗

如果是这样,为什么它将它作为一个列,为什么当我将它通过for-each循环时它会工作?这就是它为属性返回的全部内容(我去掉了这些方法):


我遗漏了什么?

似乎
获取AzureStorSimpleAccessControlRecord
行为不正常,将其输出集合作为一个整体通过管道发送,而不是逐项发送。
我已经报告了这个问题,以防你想投票修复它

通过将调用封装在
(…)
中,您应该能够解决这个问题:

(Get-AzureStorSimpleAccessControlRecord) | Where-Object { $_.Name -like '*servertest4*' }
封装在
(…)
中,使PS将集合预先转换为常规PS数组,然后按照预期通过管道发送其元素;有关背景信息,请参阅我的

但是,请注意,此解决方案总是在通过管道逐个发送项目之前预先收集所有元素

如果希望避免这种情况,可以插入虚拟管道阶段
| ForEach对象{$\u0}
,这也会强制逐项枚举:

Get-AzureStorSimpleAccessControlRecord | ForEach-Object { $_ } |
  Where-Object { $_.Name -like '*servertest4*' }

可选阅读:没有解决方案会发生什么? 下面的简化示例通过创建一个
[int[]
数组来模拟
Get-AzureStorSimpleAccessControlRecord
的不良行为,该数组通过数组构造运算符的一元形式被人为地包装在另一个数组中,

通过管道发送此包装的集合将导致它作为一个整体而不是逐项发送

$wrappedColl = , [int[]] (1, 2) # create artificially wrapped collection
现在,
Get Member
报告包装的集合类型,而不是通常情况下的单个项的类型(管道打开外部数组的包装,并按原样发送其唯一的元素-内部
[int[]
数组):

当应用
Where Object
过滤器时,作为一个整体传递的数组也会遇到阻碍,这就是问题的原因:

# Trying to extract element 2 outputs the whole array(!).
> $wrappedColl | Where-Object { $_ -eq 2 }
1
2
  • 由于
    [int[]
    数组作为一个整体传递,这就是
    $\ucode>在
    Where Object
    脚本块中绑定到的内容

  • -eq
    应用于作为数组的LHS将执行数组过滤,而不是返回简单的
    [bool]
    值,因此
    [int[]](1,2)-eq 2
    返回匹配项的数组,在本例中为
    [object[]]2
    (注意,结果数组始终是
    [object[]类型的常规PS数组)

  • 然后,在
    Where Object
    cmdlet的上下文中将生成的(单个项)数组解释为布尔值,当强制为布尔值时,任何非空数组的计算结果均为
    $true

  • 因此,由于脚本块被传递到
    其中的Object
    计算为
    $true
    ,因此输入对象被传递,在这种情况下,如前所述,输入对象是整个
    [int[]]
    数组


gm-input(Get-AzureStorSimpleAccessControlRecord)[0]
名称属性字符串名称{Get;set;}
确实显示。以这种方式运行gm和将输出导入gm之间有什么区别?啊哈!我在Get-AzureRmDataFactoryV2PipelineRun中遇到了同样的问题,它也会一次返回所有数据,并且您的解决方案工作得非常好。谢谢你的解释如此透彻。很高兴听到这有帮助,@HeatherSawatsky。
> $wrappedColl | Get-Member

   TypeName: System.Int32[]  # !! Type of the wrapped array as a whole
   ...
# Trying to extract element 2 outputs the whole array(!).
> $wrappedColl | Where-Object { $_ -eq 2 }
1
2