web-dev-qa-db-ja.com

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

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

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

あなたは何を使うのですか?どちらが良い/きれいなアプローチですか?どうして?

115
Hinek

私が知っている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を使用しない明確な理由を示していると思います。

157
JasonMArcher

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".
18
Ocaso Protal

私はこれが古いスレッドであることを理解していますが、@ JasonMArcherの受け入れられた答えを事実として取っている人にとって、それが修正されていないことに驚いています長年にわたって多くの人がそれが実際に遅延を追加し、 Out-Nullかどうか。実際、以下のテストを実行すると、[void]および$ void =への同じ「より速い」キャストがすぐにわかります。パイプラインを追加します。言い換えれば、何かにパイプするとすぐに、out-nullを使用しないというルール全体がゴミになります。

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

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

上記のすべてのテストにOut-Stringに追加のパイプを追加するだけで、#sが大幅に変更され(または単に下に貼り付けられます)、実際にわかるように、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
16
Collin Chaffin

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

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を使用します。

11
stej

個人的に、私は... | Out-Nullを使用します。なぜなら、他の人がコメントしているように、それは... > $nullおよび[void] ...と比較してより「PowerShellish」アプローチに似ているからです。 $null = ...は特定の 自動変数 を利用しており、簡単に見落とされる可能性がありますが、他の方法では、式の出力を破棄する追加の構文でそれを明らかにします。 ... | Out-Null... > $nullは式の最後に来るので、それらは効果的に「この時点までに行ったことをすべて取り除いて捨てる」ことを伝え、さらにデバッグのために簡単にコメントアウトできると思います... # | Out-Nullまたは$null =を置くことと比較した目的(例:[void]before何が起こるかを決定する式after実行。

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

確かに、値の出力を抑制することは、スクリプトの全体的なロジックを理解することと比べるとかなり小さな詳細であり、優れたコードを書く能力を身に付ける前に、コードを「弱める」ことしかできません。初心者の読む能力...あまり良くないコード。私の要点は、PowerShellに堪能な人の中には[void]$null =などに精通していない人もいる可能性があることです。 tはあなたがやろうとしていることをする最良の方法であることを意味し、言語が風変わりな構文を提供するからといって、より明確でよく知られた何かの代わりにそれを使用する必要があるという意味ではありません。*

* 私はOut-Nullが明確でよく知られていると推測していますが、$trueであることは知りません。どちらのオプションもyo feelが最も明確で、コードの将来の読者や編集者(自分自身を含む)に最もアクセスしやすく、タイプする時間や実行する時間に関係なく、それが私が推奨しているオプションですあなたが使う。

1
BACON