2
votes

Pourquoi avons-nous besoin de crochets dans cet exemple?

Pourquoi ce

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

renvoie une liste vide (semble-t-il ne pas filtrer les valeurs) mais cela

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

fonctionne? Habituellement, je n'ai pas besoin de () mais dans ce cas, ils sont obligatoires, mais pourquoi?


12 commentaires

Qu'entendez-vous exactement par "ne fonctionne pas" ?


Je pense qu'il veut dire qu'aucune sortie n'est sélectionnée, et je dois admettre que cela me semble étrange.


Il ne filtre pas. Le résultat est vide, ce qui semble ne pas filtrer les valeurs de la liste. Mais avec des parenthèses, j'obtiens un résultat correct


Lol! Juste pour jeter de l'essence sur le feu. Si vous exécutez Get-WinUserLanguageList | où {$ _. LanguageTag -eq 'en-US'} vous obtenez également des valeurs. Je n'ai jamais vu Where-object appelé sans un bloc de code comme vous l'avez.


Je ne connais pas non plus toutes les nuances avec cette syntaxe car j'utilise normalement un ScriptBlock lors du filtrage avec Where-Object , mais c'est valide.


@Adam votre version renvoie toutes les langues au lieu de filtrer les inégalités. J'ai aussi essayé -ne au lieu de -eq et j'obtiens le même résultat: tous les éléments dans les deux cas ce qui est faux (rien de filtré)


Autre chose étrange: si j'écris dir | où N et que j'appuie sur TAB, j'obtiens le nom de propriété auto-complété mais dans le cas de cette étrange applet de commande - rien n'est auto-complété. Il renvoie une liste d'éléments au lieu d'un tableau d'éléments. Alors, peut-être que @BendertheGreatest a raison - et la raison est List au lieu de Array?


@ Paul-AG: Get-WinUserLanguageList | Where-Object {$ _. LanguageTag -eq 'en-US'} ne renvoie pas toutes les langues. Je viens de tester cela localement et si j'utilise une autre balise de langue, l'entrée en-US n'est pas retournée


super étrange, j'ai copié-collé votre extrait de code et il renvoie mes 2 langues, pas seulement "en-US". Ma PSVersion est: 5.1.17763.316


Je n'ai installé qu'une seule langue, mais si je change la balise en fr-CA , je ne reçois pas mon pack en-US .


@ Paul-AG Lol! Je n'ai aucun problème à filtrer les résultats à l'aide de cet extrait. Si je change la valeur de «us-EN» en «nous» par exemple, je n'obtiens aucun résultat. Sans voir votre travail, il est difficile de dire pourquoi j'obtiens des résultats différents de votre part.


@Adam: La syntaxe simplifiée sans bloc de script a été introduite dans PowerShell v3, et elle est appelée instruction de comparaison . Typiquement , les deux formes de syntaxe sont interchangeables, mais dans ce cas particulier - étonnamment - elles ne le sont pas: l'instruction de comparaison ne renvoie rien, et la forme de bloc de script renvoie la seule et unique collection-as- un objet d'entrée entier; voir la note de bas de page dans ma réponse pour une explication.


4 Réponses :


-2
votes

FOund :) Vérifiez Get-member. C'est un tableau de retour.


0 commentaires

2
votes

Get-WinUserLanguageList renvoie un tableau d'objets System.Generic.Collection.List . Cette liste sous-jacente est ce sur quoi vous devez filtrer.

Le fait de placer l'applet de commande entre parenthèses fait dérouler la collection sous-jacente sans avoir à parcourir chaque index du tableau renvoyé. La réponse de mklement0 explique plus en détail ce comportement et pourquoi Get-WinUserLanguageList fonctionne différemment de la plupart des autres applets de commande qui renvoient des collections.


0 commentaires

1
votes

Comme mentionné ci-dessus, vous obtenez un objet de liste et non l'objet WinUserLanguage que vous attendez.

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

Vous pouvez également l'utiliser.

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                                                                                                                      


5 commentaires

C'est un peu plus chic que je pense: Get-WinUserLanguageList | Where-Object {$ _. LanguageTag -eq 'en-us'}


cela ne fonctionne pas pour moi: il renvoie TOUTES les langues, pas celle où tag est "en-US". -ne condition - la même - renvoie tout.


Sûr. Une chose à noter est que l'applet de commande Where-Object est nettement plus lente que la méthode .where (). Cela ne fera peut-être pas une différence ici, mais une bonne pratique pour les listes plus grandes.


@RoscoeT vrai vrai, mais nous ne déplaçons pas de montagnes ici :)


@BendertheGreatest Peut-être que vous n'êtes pas;)



3
votes

Habituellement, je n'ai pas besoin de () mais dans ce cas, ils sont obligatoires, mais pourquoi?

  • < convenient (...) force l'énumération des éléments d'une collection sortie par la commande incluse dans un pipeline.

  • Cela ne devrait pas être nécessaire, mais c'est dans votre cas, car Get-WinUserLanguageList présente un comportement non standard : au lieu de sortie de plusieurs objets de résultat un par un vers le pipeline, il émet une collection entière [1] en tant que sortie unique objet .

    • Sans le (...) englobant, la commande du segment de pipeline suivant - Where-Object dans votre cas - n'en reçoit donc qu'un un input - la collection entière - et opère sur it plutôt que sur les éléments un par un.
      Puisque l'objet de collection lui-même n'a pas de propriété LanguageType , rien ne correspond et vous n'obtenez aucune sortie. [2]

Comme mentionné dans les commentaires, vous pouvez diriger la sortie d'une commande vers Get-Member pour voir les types (distincts) de ses objets de sortie; pour les applets de commande standard, vous verrez les types de la sortie des objets individuels , et non un type de collection.


[1] Plus précisément, la collection est une liste générique de type [System.Collections.Generic.List [Microsoft.InternationalSettings.Commands.WinUserLanguage]] . < / p>

[2] Vous utilisez la syntaxe simplifiée PSv3 + instruction de comparaison dans votre commande - Where-Object LanguageType -eq en-US - au lieu du syntaxe de bloc de script plus verbeuse, mais plus flexible - Where-Object {$ _. LanguageType -eq 'en-US'} . Si vous aviez utilisé ce dernier, votre commande aurait accidentellement renvoyé la collection entière et donc effectivement toutes les langues. La raison en est que seule la syntaxe du bloc de script applique énumération de membres à la collection d'entrée, ce qui signifie que même si $ _ lui-même n'a pas de .LanguageTag , les éléments do et leurs valeurs sont renvoyés sous forme de tableau . Avec un tableau comme LHS, -eq agit comme un filtre, et tant que en-US est parmi les valeurs renvoyées, le < L'opération code> -eq sera toujours considérée comme $ true , provoquant le passage de l'objet d'entrée - toute la collection -.
Cet écart surprenant de comportement entre les deux formes de syntaxe apparemment équivalentes est abordé dans ce problème GitHub .


3 commentaires

semble très crédible! Probablement, cette applet de commande n'est pas écrite correctement - en violation de la convention de renvoi des collections


Juste pour ajouter à la réponse de @ mklement0. Si vous deviez voir les membres de chaque ... (Get-WinUserLanguageList) | gm vs Get-WinUserLanguageList | gm vous remarquerez la différence dans les valeurs de retour.


Oui, Get-Member ou son alias gm est un excellent outil pour inspecter les objets lorsque vous n'êtes pas sûr à quoi ressemble votre objet retourné. Il montre tous les membres de l'objet ainsi que le type.