62 votes

Peut-on utiliser LINQ dans PowerShell?

Je suis en train d'utiliser LINQ en PowerShell. Il semble que ce devrait être possible depuis PowerShell est construit sur de la .NET Framework, mais je ne peux pas le faire fonctionner. Par exemple, quand j'ai essayer le suivant (fictive) du code:

$data = 0..10

[System.Linq.Enumerable]::Where($data, { param($x) $x -gt 5 })

J'obtiens l'erreur suivante:

Impossible de trouver une surcharge pour les "Où" et le comptage d'argument: "2".

Jamais l'esprit le fait que cela pourrait être accompli avec Where-Object. Le point de cette question n'est pas de trouver un idiomatiques façon de le faire une seule opération dans PowerShell. Certaines tâches d'années-lumière plus facile de le faire en PowerShell si je pouvais utiliser LINQ.

75voto

PetSerAl Points 8475

Le problème avec ton code, c'est que PowerShell ne peut pas décider à quelle spécifiques délégué type de l' ScriptBlock instance ({ ... }) devrait être lancé. Donc il n'est pas en mesure de choisir un type de béton délégué instanciation pour le générique 2ème paramètre de la Where méthode. Et il ne ont pas la syntaxe pour spécifier un paramètre générique explicitement. Pour résoudre ce problème, vous avez besoin de jeter l' ScriptBlock exemple pour le droit délégué de vous-même:

$data = 0..10
[System.Linq.Enumerable]::Where($data, [Func[object,bool]]{ param($x) $x -gt 5 })

Pourquoi est - [Func[object, bool]] de travail, mais [Func[int, bool]] ne l'est pas?

Parce que votre $data est [object[]], pas [int[]], étant donné que PowerShell crée [object[]] tableaux par défaut; vous pouvez, cependant, de construire [int[]] cas explicitement:

$intdata = [int[]]$data
[System.Linq.Enumerable]::Where($intdata, [Func[int,bool]]{ param($x) $x -gt 5 })

40voto

mklement0 Points 12597

Pour compléter PetSerAl est utile de répondre avec une plus grande réponse pour correspondre à la question du titre générique:

Remarque: Direct prise en charge de LINQ - avec la syntaxe comparable à celle de C# est en cours de discussion pour une future version de PowerShell de Base dans cette GitHub question.

À l'aide de LINQ en PowerShell:

  • Vous avez besoin de PowerShell v3 ou supérieur.

  • Vous ne pouvez pas appeler l'extension LINQ méthodes directement sur la collecte des instances et au lieu d'invoquer les méthodes LINQ que des méthodes statiques de la [System.Linq.Enumerable] type pour lequel vous passez l'entrée de la collection en tant que premier argument.

    • Avoir à faire enlève de la fluidité de l'LINQ API, parce que la méthode de chaînage n'est plus une option. Au lieu de cela, vous devez imbriquer les appels statiques, dans l'ordre inverse.

    • E. g., au lieu de $inputCollection.Where(...).OrderBy(...) vous devez écrire [Linq.Enumerable]::OrderBy([Linq.Enumerable]::Where($inputCollection, ...), ...)

  • Fonctions d'aide et des classes:

    • Certaines méthodes, telles que .Select(), ont des paramètres qui acceptent générique Func<> des délégués (e.g, Func<T,TResult> peuvent être créés à l'aide de PowerShell code, par l'intermédiaire d'un cast appliqué à un bloc de script; par exemple:
      [Func[object, bool]] { $Args[0].ToString() -eq 'foo' }

      • Le premier paramètre de type générique d' Func<> des délégués doit correspondre au type des éléments de la collection d'entrée; gardez à l'esprit que PowerShell crée [object[]] tableaux par défaut.
    • Certaines méthodes, telles que .Contains() et .OrderBy ont des paramètres qui acceptent les objets qui implémentent des interfaces spécifiques, tels que l' IEqualityComparer<T> et IComparer<T>; en outre, les types d'entrée peut-être besoin de mettre en œuvre IEquatable<T> pour les comparaisons à fonctionner comme prévu, comme avec .Distinct(); tous ces exiger des classes compilées écrit, généralement, en C# (si vous pouvez les créer à partir de PowerShell, en passant une chaîne intégré dans le code C# de l' Add-Type applet de commande); dans PSv5+, cependant, vous pouvez également utiliser des PowerShell classes, avec certaines limitations.

  • Méthodes génériques:

    • Certains LINQ méthodes elles-mêmes sont génériques et ne nécessitent donc un paramètre de type; PowerShell ne peut pas directement appel à de telles méthodes et doit utiliser la réflexion au lieu de cela; par exemple:

      # Obtain a [string]-instantiated method of OfType<T>.
      $ofTypeString = [Linq.Enumerable].GetMethod("OfType").MakeGenericMethod([string])
      
      # Output only [string] elements in the collection.
      # Note how the array must be nested for the method signature to be recognized.
      > $ofTypeString.Invoke($null, (, ('abc', 12, 'def')))
      abc
      def
      
  • Le LINQ méthodes retourne un itérateur plutôt qu'une véritable collection.

    • Dans de nombreux cas, cependant, vous serez en mesure d'utiliser l'itérateur comme s'il s'agissait d'une collection, comme lors de l'envoi à travers le pipeline.

      • Cependant, vous ne pouvez pas obtenir le résultat le comte en invoquant .Count ni d'index dans l'itérateur; vous pouvez, cependant, utiliser membre de l'énumération.
    • Si vous ne devez les résultats dans un tableau statique pour obtenir la collection habituelle de comportement, l'envelopper de l'invocation en [Linq.Enumerable]::ToArray(...).

      • Les mêmes méthodes qui retournent des différentes structures de données existent, comme ::ToList().

Pour un exemple avancé, voir cette réponse de la mine.
Pour une vue d'ensemble de toutes les méthodes LINQ, y compris des exemples, voir cet excellent article.


En bref: l'utilisation de LINQ à partir de PowerShell est lourd et est seulement la valeur de l'effort si l'une des situations suivantes:

  • vous avez besoin de requête avancée fonctionnalités que les applets de commande PowerShell ne peut pas fournir.
  • la performance est d'une importance capitale, voir cet article.

17voto

smhetre Points 39

Si vous souhaitez obtenir LINQ comme fonctionnalité puis PowerShell a quelques applets de commande et de fonctions, par exemple: Select-Object, Where-Object, Sort-Object, Group-Object. Il a les applets de commande pour plus de LINQ fonctionnalités, comme la Projection, Restriction, de Commande, de Regroupement, de Partitionnement, etc.

Consultez le lien.

Pour plus de détails, ce lien peut être utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X