我正在尝试做一些有关 Azure 策略的报告。我最终将过滤日期,但无法过滤任何内容,因此提供以下示例。
PS C:\>$defstrings = az policy definition list --management-group "mgsandbox" # returns an array of strings
PS C:\>$def = ConvertFrom-Json -InputObject ($defstrings -join "`n") -depth 99 # converts to an array of PSCustomObject
PS C:\>$def.count
2070
PS C:\>$sel = Where-Object -inputobject $def -FilterScript { $_.displayName -eq "Kubernetes cluster containers should not share host process ID or host IPC namespace" }
PS C:\>$sel.count
2070
PS C:\> $def[0].displayName -eq "Kubernetes cluster containers should not share host process ID or host IPC namespace"
False
虽然我可能会在 displayName 上发现多个命中,但显然有一组非零的 displayName 与过滤器不匹配,但选择却获得了所有这些。
有什么建议我的语法有什么问题吗?看起来很简单。
请勿将
-InputObject
参数 与 Where-Object
一起使用; 相反,通过管道提供输入:
# Use the pipeline to provide input, don't use -InputObject
$def | Where-Object -FilterScript { $_.displayName -eq "Kubernetes cluster containers should not share host process ID or host IPC namespace" }
在大多数 cmdlet 中,
-InputObject
参数只是一个实现细节,其目的是促进管道输入,不能直接有意义地使用;请参阅此答案了解更多信息,以及GitHub问题#4242进行讨论。
你尝试过的:
当您使用-InputObject
时,作为集合(可枚举)的参数将作为一个整体传递给cmdlet,而在管道中使用相同的会导致其枚举,即集合的元素是通过了,一一。 一个简化的例子:
# Sample array.
$arr = 1, 2, 3
# WRONG: array is passed *as a whole*
# and in this case outputs *all* its elements.
# -> 1, 2, 3
Where-Object -InputObject $arr { $_ -eq 2 }
也就是说,传递给 Where-Object
的脚本块被执行once,自动
$_
变量绑定到整个数组,因此上面的效果相当于:
if ($arr -eq 2) { $arr }
由于 $arr -eq 2
在布尔上下文(
$true
条件)中计算为
if
,因此
$arr
作为一个整体被输出(尽管在输出时它被枚举),给人的印象是没有发生过滤。
$arr -eq 2
计算为
$true
的原因是
-eq
运算符等支持arrays 作为其 LHS,在这种情况下,行为会更改为 filtering,通过返回 的 子数组匹配元素而不是布尔值,以便
1, 2, 3 -eq 2
产生
@(2)
(包含一个匹配元素
2
的数组),并将
@(2)
强制转换为布尔值产生
$true
(
[bool] @(2)
)。[1]
$false
(例如,
$_ -eq 5
),则根本不会产生任何输出。相比之下,如果您使用管道,您将获得所需的行为:
# Sample array.
$arr = 1, 2, 3
# OK: Array elements are enumerated, i.e.
# sent *one by one* through the pipeline.
# -> 2
$arr | Where-Object{ $_ -eq 2 }
来绕过管道: 注意:这需要先收集内存中的所有输入;然而,特别是当数据已经在内存中时,这种方法的性能比管道方法更好:
# OK:
# -> 2 (wrapped in a collection)
@(1, 2, 3).Where({ $_ -eq 2 })
注意:.Where()
always 会输出类似数组的 collection,即使只有一个 single 对象与过滤器匹配。但实际上,这通常并不重要。
[1] 有关 PowerShell 的布尔值强制转换规则的摘要,请参阅此答案的底部部分。