web-dev-qa-db-fra.com

Quelle est la meilleure façon (plus propre) d'ignorer la sortie dans PowerShell?

Supposons que vous ayez une méthode ou une applet de commande qui retourne quelque chose, mais vous ne voulez pas l'utiliser et vous ne voulez pas la sortir. J'ai trouvé ces deux manières:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

Qu'est ce que tu utilises? Quelle est l'approche meilleure/plus propre? Pourquoi?

115
Hinek

Je viens de faire quelques tests sur les quatre options que je connais.

Measure-Command {$(1..1000) | Out-Null}

TotalMilliseconds : 76.211

Measure-Command {[Void]$(1..1000)}

TotalMilliseconds : 0.217

Measure-Command {$(1..1000) > $null}

TotalMilliseconds : 0.2478

Measure-Command {$null = $(1..1000)}

TotalMilliseconds : 0.2122

## Control, times vary from 0.21 to 0.24
Measure-Command {$(1..1000)}

TotalMilliseconds : 0.2141

Je suggérerais donc que vous utilisiez autre chose que Out-Null en raison des frais généraux. La prochaine chose importante à mes yeux serait la lisibilité. J'aime bien rediriger vers $null et réglage égal à $null moi même. J'avais l'habitude de préférer le casting à [Void], mais cela peut ne pas être aussi compréhensible quand on regarde le code ou pour les nouveaux utilisateurs.

Je suppose que je préfère légèrement rediriger la sortie vers $null.

Do-Something > $null

Éditer

Après le commentaire de stej à nouveau, j'ai décidé de faire quelques tests supplémentaires avec les pipelines pour mieux isoler les frais généraux liés à l'élimination de la sortie.

Voici quelques tests avec un pipeline simple de 1000 objets.

## Control Pipeline
Measure-Command {$(1..1000) | ?{$_ -is [int]}}

TotalMilliseconds : 119.3823

## Out-Null
Measure-Command {$(1..1000) | ?{$_ -is [int]} | Out-Null}

TotalMilliseconds : 190.2193

## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}

TotalMilliseconds : 119.7923

Dans ce cas, Out-Null a environ 60% de frais généraux et > $null a des frais généraux d’environ 0,3%.

Addendum 2017-10-16: Au départ, j'avais négligé une autre option avec Out-Null, l'utilisation du -inputObject paramètre. En utilisant cela, la surcharge semble disparaître, mais la syntaxe est différente:

Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})

Et maintenant, quelques tests avec un simple pipeline de 100 objets.

## Control Pipeline
Measure-Command {$(1..100) | ?{$_ -is [int]}}

TotalMilliseconds : 12.3566

## Out-Null
Measure-Command {$(1..100) | ?{$_ -is [int]} | Out-Null}

TotalMilliseconds : 19.7357

## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}

TotalMilliseconds : 12.8527

Encore ici Out-Null a environ 60% de frais généraux. Tandis que > $null a une surcharge d'environ 4%. Les chiffres ici varient un peu d’un test à l’autre (je me suis présenté à chacun environ 5 fois et j’ai choisi le juste milieu). Mais je pense que cela montre une raison claire de ne pas utiliser Out-Null.

157
JasonMArcher

Il y a aussi le Out-Null cmdlet, que vous pouvez utiliser dans un pipeline, par exemple, Add-Item | Out-Null.

Page de manuel pour Out-Null

NAME
    Out-Null

SYNOPSIS
    Deletes output instead of sending it to the console.


SYNTAX
    Out-Null [-inputObject <psobject>] [<CommonParameters>]


DETAILED DESCRIPTION
    The Out-Null cmdlet sends output to NULL, in effect, deleting it.


RELATED LINKS
    Out-Printer
    Out-Host
    Out-File
    Out-String
    Out-Default

REMARKS
     For more information, type: "get-help Out-Null -detailed".
     For technical information, type: "get-help Out-Null -full".
18
Ocaso Protal

Je me rends compte que c’est un vieux fil conducteur, mais pour ceux qui prennent la réponse acceptée de @ JasonMArcher ci-dessus, je suis surpris qu’elle n’ait pas été corrigée. Nombre d’entre nous savent depuis des années que le PIPELINE ajoute le retard et RIEN à faire. c'est Out-Null ou pas. En fait, si vous exécutez les tests ci-dessous, vous constaterez rapidement que les mêmes transformations "plus rapides" vers [void] et $ void = que nous utilisions tous pendant des années en pensant que c'était plus rapide, sont JUSTE LENT et TRES LENT quand vous ajoutez TOUT pipeline, que ce soit. En d'autres termes, dès que vous dirigez n'importe quoi, la règle de ne pas utiliser out-null est mise à la poubelle.

La preuve, les 3 derniers tests de la liste ci-dessous. L'horrible Out-null était de 32339,3792 millisecondes, mais attendez - à quelle vitesse le casting était-il plus rapide? 34121,9251 ms?!? WTF? Ce sont de vrais numéros sur mon système, le casting de VOID était en fait plus lent. Que diriez-vous de = $ null? 34217.685ms ..... encore friggin plus petit! Ainsi, comme le montrent les trois derniers tests simples, Out-Null est en réalité plus rapide dans de nombreux cas lorsque le pipeline est déjà utilisé.

Alors, pourquoi ça? Facile. C'est et a toujours été une hallucination à 100% que la tuyauterie vers Out-Null était plus lente. C’est cependant que le TUYAUTERIE est ralenti, et ne le savions-nous pas déjà au moyen d’une logique de base? Nous ne savons peut-être pas COMBIEN de temps, mais ces tests racontent certainement une histoire sur le coût d'utilisation du pipeline si vous pouvez l'éviter. Et nous ne nous sommes pas trompés à 100%, car il existe un très petit nombre de scénarios réels dans lesquels out-null est diabolique. Quand? Lorsque vous ajoutez Out-Null, vous ajoutez l’activité de pipeline UNIQUEMENT. En d'autres termes .... la raison pour laquelle une commande simple comme $ (1..1000) | Out-Null comme indiqué ci-dessus a montré la vérité.

Si vous ajoutez simplement un tuyau supplémentaire à Out-String à chaque test ci-dessus, le nombre de # change radicalement (ou vous ne faites que coller ceux ci-dessous) et, comme vous pouvez le constater, le paramètre Out-Null devient plus rapide dans de nombreux cas:

$GetProcess = Get-Process

# Batch 1 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Out-Null 
} 
}).TotalMilliseconds

# Batch 1 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess) 
} 
}).TotalMilliseconds

# Batch 1 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess 
} 
}).TotalMilliseconds

# Batch 2 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Select-Object -Property ProcessName | Out-Null 
} 
}).TotalMilliseconds

# Batch 2 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Select-Object -Property ProcessName ) 
} 
}).TotalMilliseconds

# Batch 2 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Select-Object -Property ProcessName 
} 
}).TotalMilliseconds

# Batch 3 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name | Out-Null 
} 
}).TotalMilliseconds

# Batch 3 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name ) 
} 
}).TotalMilliseconds

# Batch 3 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name 
} 
}).TotalMilliseconds

# Batch 4 - Test 1 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$GetProcess | Out-String | Out-Null 
} 
}).TotalMilliseconds

# Batch 4 - Test 2 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
[void]($GetProcess | Out-String ) 
} 
}).TotalMilliseconds

# Batch 4 - Test 3 
(Measure-Command { 
for ($i = 1; $i -lt 99; $i++) 
{ 
$null = $GetProcess | Out-String 
} 
}).TotalMilliseconds
16
Collin Chaffin

J'envisagerais d'utiliser quelque chose comme:

function GetList
{
  . {
     $a = new-object Collections.ArrayList
     $a.Add(5)
     $a.Add('next 5')
  } | Out-Null
  $a
}
$x = GetList

Sortie de $a.Add n'est pas renvoyé - cela vaut pour tous les $a.Add appels de méthode. Sinon, vous auriez besoin de préfixer [void] avant chaque appel.

Dans des cas simples, j'irais avec [void]$a.Add car il est évident que la sortie ne sera pas utilisée et est rejetée.

11
stej

Personnellement, j'utilise ... | Out-Null Car, comme d'autres l'ont déjà fait remarquer, cela ressemble davantage à l'approche "PowerShellish" comparée à ... > $null Et [void] .... $null = ... Exploite une variable spécifique variable automatique et peut être facile à ignorer, alors que les autres méthodes indiquent clairement, avec une syntaxe supplémentaire, que vous souhaitez supprimer le résultat d'une expression. Parce que ... | Out-Null Et ... > $null Viennent à la fin de l'expression, je pense qu'ils communiquent efficacement "prend tout ce que nous avons fait jusqu'à présent et le jette", plus tu pourras les commenter plus facilement à des fins de débogage (par exemple ... # | Out-Null), comparé à mettre $null = ou [void] avant l'expression pour déterminer ce qui se passe après son exécution.

Mais regardons un autre point de repère: pas le temps nécessaire pour exécuter chaque option, mais le temps nécessaire pour déterminer le rôle de chaque option . Ayant travaillé dans des environnements avec des collègues qui n’étaient pas habitués à PowerShell ou même au scripting, j’ai tendance à essayer d’écrire mes scripts de manière à ce que toute personne arrivant quelques années plus tard qui ne comprend même pas la langue dans laquelle elle se penche puisse avoir une se battre pour savoir ce qu'il fait car ils pourraient être obligés de le soutenir ou de le remplacer. Cela ne m’a jamais semblé une raison pour utiliser une méthode avant les autres jusqu’à présent, mais imaginons que vous êtes dans cette position et que vous utilisez la commande help ou votre moteur de recherche préféré pour essayer de trouver ce que Out-Null Fait. Vous obtenez immédiatement un résultat utile, non? Essayez maintenant de faire de même avec [void] Et $null =. Pas si facile, n'est-ce pas?

Certes, la suppression de la sortie d’une valeur est un détail assez mineur par rapport à la compréhension de la logique générale d’un script, et vous ne pouvez essayer que de "bousiller" votre code avant d’échanger votre capacité à écrire du bon code pour une la capacité du novice à lire ... pas si bon code. Selon moi, il est possible que certains utilisateurs maîtrisant parfaitement PowerShell ne connaissent même pas [void], $null =, Etc., et simplement parce que ceux-ci peuvent s'exécuter plus rapidement ou prendre moins de frappes au clavier, ne veut pas dire que ce soit la meilleure façon de faire ce que vous essayez de faire, et ce n’est pas parce qu’un langage vous donne une syntaxe décalée que vous devriez l’utiliser au lieu de quelque chose de plus clair et mieux connu.*

* Je présume que Out-Null Est clair et bien connu, ce que je ne sais pas être $true. Quelle que soit l'option que vous estimez qu'elle est la plus claire et la plus accessible pour les futurs lecteurs et rédacteurs de votre code (vous-même inclus), quels que soient le délai de frappe et l'heure. to-execute, c'est l'option que je vous recommande d'utiliser.

1
BACON