Зачем нам нужны скобки в этом примере? - PullRequest
2 голосов
/ 10 мая 2019

Почему это

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

возвращает пустой список (кажется, он не фильтрует значения), но это

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

работает? Обычно мне не нужно (), но в этом случае они обязательны, но зачем?

Ответы [ 4 ]

3 голосов
/ 10 мая 2019

Обычно я не нуждаюсь (), но в этом случае они обязательны, но почему?

  • (...) принудительное перечисление элементов коллекции, выводимых вложенной командой в конвейер.

  • Это не должно быть необходимым, но в вашем случае, потому что Get-WinUserLanguageList демонстрирует нестандартное поведение : вместо вывода нескольких конвейерных объектов один за другим в конвейер, выдает всю коллекцию [1] как один объект вывода .

    • Без включающего (...), команда в следующем сегменте конвейера - Where-Object в вашем случае - поэтомуполучает только один ввод - всю коллекцию - и работает с it , а не с элементами один за другим.
      Поскольку сам объект коллекции не имеет свойства LanguageType, ничегосовпадения, и вы не получите выходных данных. [2]

Как упомянуто вЗначит, вы можете направить вывод команды в Get-Member, чтобы увидеть (различные) типы ее выходных объектов;для стандартных командлетов вы увидите типы вывода отдельных объектов , а не тип коллекции.


[1] В частности, коллекция представляет собой общий списоктипа [System.Collections.Generic.List[Microsoft.InternationalSettings.Commands.WinUserLanguage]].

[2] Вы используете упрощенный синтаксис оператора сравнения PSv3 + в своей команде - Where-Object LanguageType -eq en-US - вместо более подробного, но более гибкий синтаксис блока скриптов - Where-Object { $_.LanguageType -eq 'en-US' }.Если бы вы использовали последний вариант, ваша команда случайно вернула бы всю коллекцию и, таким образом, эффективно все языки.Причина в том, что только синтаксис блока сценариев применяет перечисление членов к входной коллекции, что означает, что даже если $_ не имеет свойства .LanguageTag, элементы do, и их значения возвращаются в виде массива .С массивом в качестве LHS -eq действует как фильтр, и, пока en-US составляет среди возвращаемых значений, операция -eq будет по-прежнему считаться $true, вызывая вводобъект - вся коллекция - для прохождения.
Это удивительное несоответствие в поведении между двумя, казалось бы, эквивалентными синтаксическими формами обсуждается в этом выпуске GitHub .

2 голосов
/ 10 мая 2019

Get-WinUserLanguageList возвращает массив System.Generic.Collection.List объектов.Этот базовый список - это то, что вам нужно отфильтровать.

Помещение командлета в скобки развертывает базовую коллекцию без необходимости перебирать каждый индекс в возвращаемом массиве.Ответ mklement0 объясняет больше об этом поведении и почему Get-WinUserLanguageList работает иначе, чем большинство других командлетов, которые возвращают коллекции.

1 голос
/ 10 мая 2019

Как упоминалось выше, вы получаете объект списка, а не ожидаемый объект 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'})
0 голосов
/ 10 мая 2019

НАЙДЕН :) Проверьте Get-member.Это возвращаемый массив.

...