PowerShellで出力を無視するより良い(よりクリーンな)方法は何ですか?[閉まっている]


134

何かを返すメソッドまたはコマンドレットがあるが、それを使用したくなく、出力したくないとします。私はこれらの2つの方法を見つけました:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

あなたは何を使うのですか?より良い/よりクリーンなアプローチはどれですか?どうして?


1
[void]バージョンのように...まだ私には向いていませんが、覚えておきましょう。
Massif 2011年

回答:


181

私が知っている4つのオプションのいくつかのテストを行いました。

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

だから私はあなたがOut-Nullオーバーヘッドのため以外のものを使用することをお勧めします。次に重要なのは、読みやすさです。私はリダイレクトし$null$null自分と同じに設定するのが好きです。以前はにキャストすることを好んで使用して[Void]いましたが、コードを一瞥したときや新しいユーザーにとってはそれほど理解しにくいかもしれません。

私は出力をにリダイレクトすることをわずかに好むと思い$nullます。

Do-Something > $null

編集する

stejのコメントが再度出た後、出力を破棄するオーバーヘッドをより適切に分離するために、パイプラインを使用してさらにいくつかのテストを行うことにしました。

以下は、単純な1000オブジェクトパイプラインを使用したいくつかのテストです。

## 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

この場合、にOut-Nullは約60%のオーバーヘッドがあり、> $null約0.3%のオーバーヘッドがあります。

補遺2017-10-16:パラメータのOut-Null使用という別のオプションを見落としました-inputObject。これを使用するとオーバーヘッドがなくなるように見えますが、構文は異なります。

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

次に、単純な100オブジェクトパイプラインを使用したいくつかのテストについて説明します。

## 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

ここでもOut-Null、約60%のオーバーヘッドがあります。一方> $null、オーバーヘッドは約4%です。ここでの数値は、テストごとに少し異なります(私はそれぞれ約5回実行して、中間点を選びました)。でも、使わない理由は明らかだと思いますOut-Null


1
私は通常、言語行の一部であるものにはVOIDを使用し、
それでも

25
Out-Null多分オーバーヘッドです。しかし、1つのオブジェクトをOut-Null0.076ミリ秒にパイプ処理する場合、imhoはスクリプト言語としては依然として完全に
適切

1
私はこれを少しいじっていましたが、Out-Null -InputObject($(1..1000)|?{$ _ -is [int]})を使用することで、[void]と> $ nullで最高のパフォーマンスが得られます。
tomohulk 2017

1
良い点、それは顕著なオーバーヘッドがないようです。
JasonMArcher 2017年

5
何かを達成するためのさまざまな方法を比較するためのベンチマークがあることは常に良いことですが、ここで引き出すことができる他の結論を見逃さないでください。パフォーマンスの違いが無視できる数十万倍の値を破棄する必要がある場合を除きます。ここでミリ秒が重要な場合は、最初にPowerShellを使用するべきではありません。オプションがこれらの点でどのようにランク付けされるかについて判断を行わなくても、読みやすさやプログラマーの意図を表現するなど、他の品質のために速度を犠牲にすることは必ずしも悪いことではありません。
BACON、2018

22

私はこれが古いスレッドであることを理解していますが、@ JasonMArcherの上記の回答を実際に受けている人にとって、何年も前から修正されていないことに驚いています。実際には、パイプラインが遅延を追加しているのかどうかは関係ありません。 Out-Nullかどうか。実際、以下のテストを実行すると、[void]および$ void =への同じ「より高速な」キャストが、何年もの間ずっと高速であると考えていたが、実際には低速であり、実際には非常に低速であることがすぐにわかります。パイプラインを追加します。つまり、何かにパイプするとすぐに、out-nullを使用しないというルール全体がゴミ箱に入ります。

下のリストの最後の3つのテストの証明。恐ろしいOut-nullは32339.3792ミリ秒でしたが、待ってください-[void]へのキャストはどれだけ速くなりましたか?34121.9251 ms?!?WTF?これらは私のシステム上のREAL#であり、VOIDへのキャストは実際には遅くなりました。= $ nullはどうですか?34217.685ms .....それでもゆっくりと遅い したがって、最後の3つの簡単なテストが示すように、パイプラインが既に使用されている場合、多くの場合、Out-Nullは実際には高速です。

それで、これはなぜですか?シンプル。Out-Nullへのパイプが遅かったのは100%幻覚でした。ただし、PIPING TO ANYTHINGの方が低速であり、基本的なロジックでそれを知っているのではないでしょうか。速度が遅いことを知らないだけかもしれませんが、これらのテストは、パイプラインを使用するコストを回避できる場合は、そのコストについてのストーリーを確実に伝えます。また、アウトヌルが悪である実際のシナリオは非常に少ないため、100%間違っているわけではありません。いつ?Out-Nullを追加すると、パイプラインアクティビティのみが追加されます。言い換えれば... $(1..1000)のような単純なコマンドの理由| 上記のOut-Nullはtrueを示しました。

上記のすべてのテストにOut-Stringにパイプを追加するだけで、#は根本的に変化し(または単に下記のものを貼り付け)、実際にわかるように、多くの場合、Out-Nullは実際より高速になります。

$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

この重要なポイントを作るための+1。実際、Out-Nullパイプラインを使用するように強制することは何もありません。そのため、パイプラインのオーバーヘッドを示す最善の方法は、パイプラインのOut-Null有無にかかわらず呼び出すことです。私のシステムでは、10,000回の反復で、0.576秒とOut-Null -InputObject $GetProcess5.656秒(ほぼ10倍遅い)が得られ$GetProcess | Out-Nullます。
BACON、2018

こんにちはコリン、あなたの答えをありがとう。私はあなたのサンプルを実行しましたが、すべてのバッチで[void]$nullそれでもより優れてい| Out-Nullます。これはパイプラインが原因で発生し、後のバッチでデルタが縮小することがわかりますが、私のマシンでOut-Nullはどのバッチでも高速に実行されません。
Hinek 2018

しかしもちろん、パフォーマンスはすべてではなく、読みやすさも考慮すべきであると主張する人々に同意する必要があります。
Hinek 2018

@Hinekあなたのコメントは、コリンが言っていたことの要点を逃したことを示唆しています。はい、[void]そして- $nullよりも優れ| Out-Nullてい|ます。Out-Null -InputObject (expression)比較してみてください。
ジョナサンギルバート

19

Out-Nullたとえば、パイプラインで使用できるコマンドレットもありますAdd-Item | Out-Null

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".

ジェイソンの答えの小さなベンチマークテストの結果についてどう思いますか?
Hinek

非常に興味深い。特にOut-Nullと他の方法との非常に大きな違い。[void]Out-Nullソリューションの方が「パワーシェルっぽい」ように見えても、私は切り替えると思います。
Ocaso Protal 2011

私はまだわからない、私の好きな方法は何ですか。stejがすでにコメントしたように、この大きな違いでさえほとんど意味がないようです。
Hinek

2
@Hinek [void]は非常に明確に見えます(私が言ったようにpowershellishではありません)。行の先頭に、この行に出力がないことがわかります。したがって、これは別の利点であり、大きなループでOut-Nullを実行すると、パフォーマンスが問題になる可能性があります;)
Ocaso Protal

11

私は次のようなものの使用を検討します:

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

からの出力$a.Addは返されません-すべての$a.Addメソッド呼び出しに対して保持されます。それ以外の場合は[void]、各呼び出しの前に付加する必要があります。

単純なケース[void]$a.Addでは、出力が使用されずに破棄されることがはっきりしているので、私はそれを行います。


2

個人的には、... | Out-Null他のユーザーがコメントしているように、... > $nullおよびと比較して「PowerShellish」のアプローチのように見えるため、これを使用してい[void] ...ます。 $null = ...は特定の自動変数を利用しており、見過ごされがちですが、他のメソッドでは、追加の構文を使用して、式の出力を破棄することを明確にしています。ので... | Out-Null... > $null、式の終わりに来る私は、彼らが効果的に「我々はこれまでに行ってきたすべてのものを取って、それを捨てる」、プラスあなたは(例えばデバッグ目的のために簡単にそれらをコメントアウトすることができます通信すると思います... # | Out-Null)、パッティングに比べ$null =あるいは[void] 実行後に何が起こるかを決定する式。

ただし、別のベンチマークを見てみましょう。各オプションの実行にかかる時間ではなく、各オプションの機能理解するのにかかる時間です。PowerShellやスクリプト作成の経験がまったくない同僚との環境で働いていたため、自分が見ている言語を理解できなくても、数年後にやって来る誰かが彼らがそれをサポートまたは交換しなければならない立場にあるかもしれないので、それが何をしているのかを理解するチャンスと戦う。これは、今まで他の方法よりも1つの方法を使用する理由としては一度も発生していませんが、その位置にいて、helpコマンドまたはお気に入りの検索エンジンを使用して、Out-Nullします。すぐに役立つ結果が得られますよね?次に、[void]およびで同じことを実行してください$null =。それほど簡単ではありませんか?

確かに、値の出力を抑制することは、スクリプトの全体的なロジックを理解するのに比べるとかなり細かい部分であり、適切なコードを書く能力をトレードオフする前に、コードをそんなに「弱める」ことができます初心者の読む能力...あまり良くないコード。私のポイントである、それはPowerShellで堪能な人もが持つさえ慣れていない可能性があります[void]$null =など、及びそれらがより速く実行するか、型に少ないキーストロークがかかる場合がありますという理由だけで、彼らが行うための最善の方法だという意味ではありませんあなたがやろうとしていること、そして言語が風変わりな構文を与えるからといって、より明確でよく知られているものの代わりにそれを使用するべきだという意味ではありません。*

*私はそれOut-Nullが明確でよく知られていると思いますが、私にはわかりません$true。どちらのオプションあなたは感じているが、私はあなたが使用を推奨していますオプションですが、関係なく、タイム・ツー・タイプまたは時間に実行する、(自分を含む)、将来のリーダーとあなたのコードの編集者がアクセス可能な明確な、最もです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.