不要使用-InputObject
argument with 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" }
In mostcmdlet,-InputObject
参数只是一个实施细节其目的是方便管道输入并且不能被有意义地使用directly; see 这个答案了解更多信息,以及GitHub 问题 #4242进行讨论。
As for 你尝试过什么:
当你使用-InputObject
,传递一个集合(可枚举)的参数作为一个整体到 cmdlet,而使用相同的在管线中导致其枚举,即集合的elements都通过了,逐个.
一个简化的例子:
# 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 }
Since $arr -eq 2
评估为$true
在布尔上下文中(if
有条件),$arr
作为一个整体是输出(尽管在输出时它被枚举),给人的印象是没有进行过滤。
- The reason that
$arr -eq 2
evaluates to $true
is that the -eq
operator, among others, supports arrays as its LHS, in which case the behavior changes to filtering, by returning the sub-array of matching elements instead of a Boolean, so that 1, 2, 3 -eq 2
yields @(2)
(an array containing the one matching element, 2
), and coercing @(2)
to a Boolean yields $true
([bool] @(2)
).[1]
相反,如果隐含条件产生$false
(e.g., $_ -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 }
或者,您可以bypass管道通过使用固有的.Where() method:
注意:这需要先收集内存中的所有输入;然而,特别是当数据已经在内存中时,这种方法的性能比管道方法更好:
# OK:
# -> 2 (wrapped in a collection)
@(1, 2, 3).Where({ $_ -eq 2 })
Note: .Where()
always输出类似数组的收藏,即使只有一个single对象与过滤器匹配。但实际上,这通常并不重要。
[1] For a summary of PowerShell's to-Boolean coercion rules, see the bottom section of this answer.