为什么在这个例子中我们需要括号?
Why do we need brackets in this example?
为什么会这样
Get-WinUserLanguageList | Where-Object LanguageTag -eq en-US
returns 空列表(似乎不过滤值)但是这个
(Get-WinUserLanguageList) | Where-Object LanguageTag -eq en-US
有用吗?通常我不需要 ()
但在这种情况下它们是强制性的,但为什么?
已找到 :)
检查 Get-member。
这是 return 数组。
Get-WinUserLanguageList
return 是 System.Generic.Collection.List
个对象的数组。该基础列表是您需要过滤的内容。
将 cmdlet 放在括号中可以展开基础集合,而不必遍历 returned 数组中的每个索引。 的回答解释了有关此行为的更多信息,以及为什么 Get-WinUserLanguageList
与 return 集合的大多数其他 cmdlet 的工作方式不同。
如上所述,您得到的是一个列表对象,而不是您期望的 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'})
Usually I don't need () but in this case they are mandatory, but why?
(...)
强制枚举 管道中包含的命令输出的集合元素。
这应该不是必需的,但在你的情况下是这样,因为 Get-WinUserLanguageList
表现出 非标准行为:不是将多个结果对象一个一个输出到管道,它发出一个整个集合[1]作为单一输出对象.
- 没有封闭的
(...)
,下一个管道段中的命令 - 在您的情况下为 Where-Object
- 因此仅接收 一个 输入 - 整个集合- 并且在 it 上操作,而不是一个一个地操作元素。
由于集合对象本身没有 LanguageType
属性,没有任何匹配项,因此您没有输出。[2]
如评论中所述,您可以将命令的输出通过管道传输到 Get-Member
以查看其输出对象的(不同)类型;对于标准 cmdlet,您会看到 单个对象 输出的类型,而不是集合类型。
[1] 具体来说,集合是 [System.Collections.Generic.List[Microsoft.InternationalSettings.Commands.WinUserLanguage]]
.
类型的泛型列表
[2] 您在命令中使用了简化的 PSv3+ 比较语句 语法 - Where-Object LanguageType -eq en-US
- 而不是更冗长的语法,但是更灵活的 script-block 语法 - Where-Object { $_.LanguageType -eq 'en-US' }
。如果您使用后者,您的命令会意外返回 整个集合 ,从而有效地返回 所有 语言。原因是只有 script-block 语法将 member-access enumeration 应用于输入集合,这意味着即使 $_
本身没有 .LanguageTag
属性, elements 做,它们的值作为 array 返回。使用数组作为 LHS,-eq
充当过滤器,只要 en-US
在 返回值中 ,-eq
操作将仍被视为 $true
,导致输入对象 - 整个集合 - 被传递。
this GitHub issue.
中讨论了这两种看似等效的语法形式之间令人惊讶的行为差异
为什么会这样
Get-WinUserLanguageList | Where-Object LanguageTag -eq en-US
returns 空列表(似乎不过滤值)但是这个
(Get-WinUserLanguageList) | Where-Object LanguageTag -eq en-US
有用吗?通常我不需要 ()
但在这种情况下它们是强制性的,但为什么?
已找到 :) 检查 Get-member。 这是 return 数组。
Get-WinUserLanguageList
return 是 System.Generic.Collection.List
个对象的数组。该基础列表是您需要过滤的内容。
将 cmdlet 放在括号中可以展开基础集合,而不必遍历 returned 数组中的每个索引。 Get-WinUserLanguageList
与 return 集合的大多数其他 cmdlet 的工作方式不同。
如上所述,您得到的是一个列表对象,而不是您期望的 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'})
Usually I don't need () but in this case they are mandatory, but why?
(...)
强制枚举 管道中包含的命令输出的集合元素。这应该不是必需的,但在你的情况下是这样,因为
Get-WinUserLanguageList
表现出 非标准行为:不是将多个结果对象一个一个输出到管道,它发出一个整个集合[1]作为单一输出对象.- 没有封闭的
(...)
,下一个管道段中的命令 - 在您的情况下为Where-Object
- 因此仅接收 一个 输入 - 整个集合- 并且在 it 上操作,而不是一个一个地操作元素。
由于集合对象本身没有LanguageType
属性,没有任何匹配项,因此您没有输出。[2]
- 没有封闭的
如评论中所述,您可以将命令的输出通过管道传输到 Get-Member
以查看其输出对象的(不同)类型;对于标准 cmdlet,您会看到 单个对象 输出的类型,而不是集合类型。
[1] 具体来说,集合是 [System.Collections.Generic.List[Microsoft.InternationalSettings.Commands.WinUserLanguage]]
.
[2] 您在命令中使用了简化的 PSv3+ 比较语句 语法 - Where-Object LanguageType -eq en-US
- 而不是更冗长的语法,但是更灵活的 script-block 语法 - Where-Object { $_.LanguageType -eq 'en-US' }
。如果您使用后者,您的命令会意外返回 整个集合 ,从而有效地返回 所有 语言。原因是只有 script-block 语法将 member-access enumeration 应用于输入集合,这意味着即使 $_
本身没有 .LanguageTag
属性, elements 做,它们的值作为 array 返回。使用数组作为 LHS,-eq
充当过滤器,只要 en-US
在 返回值中 ,-eq
操作将仍被视为 $true
,导致输入对象 - 整个集合 - 被传递。
this GitHub issue.