为什么在此示例中需要括号?

时间:2019-05-10 15:04:36

标签: powershell enumeration parentheses

为什么这样

Get-WinUserLanguageList | Where-Object LanguageTag -eq en-US

返回空列表(似乎它不过滤值),但这

(Get-WinUserLanguageList) | Where-Object LanguageTag -eq en-US

有效吗?通常我不需要(),但是在这种情况下,它们是强制性的,但是为什么呢?

4 个答案:

答案 0 :(得分:3)

  

通常我不需要(),但在这种情况下,它们是强制性的,但是为什么呢?

  • (...)强制枚举,由管道中包含的命令对集合输出的元素进行枚举。

  • 这不是必须的,但是在您的情况下,因为 Get-WinUserLanguageList表现出非标准行为 :而不是输出多个结果对象< em>一条到管道,它发出整个集合 [1] 作为单个输出对象

    • 没有封闭的(...),下一个管道段中的命令-在您的情况下为Where-Object-因此仅接收一个输入-整个集合-并在< em> it ,而不是一一对应。
      由于集合对象本身没有LanguageType属性,因此没有任何匹配项,并且您也不会获得任何输出。 [2]

如注释中所述,您可以将命令的输出通过管道传递到Get-Member,以查看其输出对象的(不同的)类型。对于标准cmdlet,您会看到单个对象输出的类型,而不是集合类型。


[1]具体来说,该集合是类型为[System.Collections.Generic.List[Microsoft.InternationalSettings.Commands.WinUserLanguage]]的通用列表。

[2]您在命令中使用简化的PSv3 + 比较语句语法-Where-Object LanguageType -eq en-US-而不是更冗长但更灵活的脚本块语法- Where-Object { $_.LanguageType -eq 'en-US' }。如果您使用了后者,那么您的命令将不小心返回整个集合,从而有效地返回了所有语言。原因是只有脚本块语法将成员枚举应用于输入集合,这意味着即使$_本身没有.LanguageTag属性,< em> elements ,它们的值作为 array 返回。对于LHS数组,-eq充当过滤器,并且只要en-US在返回的值中 中,仍将考虑-eq操作$true,导致输入对象(整个集合)通过。
this GitHub issue中讨论了两种看似等效的语法形式之间这种令人惊讶的行为差异。

答案 1 :(得分:2)

Get-WinUserLanguageList返回一个System.Generic.Collection.List对象的数组。该基础列表是您需要过滤的内容。

将cmdlet放在括号中可以展开基础集合,而不必迭代返回数组中的每个索引。 mklement0的答案进一步说明了这种行为,以及为什么Get-WinUserLanguageList与大多数其他返回集合的cmdlet的工作原理不同。

答案 2 :(得分:1)

如上所述,您将获得一个列表对象,而不是您期望的WinUserLanguage对象。

PS C:\Users\admin user> $test = Get-WinUserLanguageList

PS C:\Users\admin user> $test.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                           
-------- -------- ----                                     --------                                                                                                                           
True     True     List`1                                   System.Object                                                                                                                      



PS C:\Users\admin user> $test[0].GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                           
-------- -------- ----                                     --------                                                                                                                           
True     False    WinUserLanguage                          System.Object                                                                                                                      

您也可以使用它。

(Get-WinUserLanguageList).where({$_.LanguageTag -eq 'en-US'})

答案 3 :(得分:-2)

基金会:) 选中获取成员。 它是返回数组。