什么';在PowerShell中忽略输出的更好(更干净)方法是什么?

什么';在PowerShell中忽略输出的更好(更干净)方法是什么?,powershell,null,void,Powershell,Null,Void,假设您有一个返回某些内容的方法或cmdlet,但您不想使用它,也不想输出它。我发现有两种方法: Add-Item > $null [void]Add-Item Add-Item | Out-Null 你用什么?哪种方法更好/更干净?为什么?还有cmdlet,您可以在管道中使用它,例如,additem | Out Null Do-Something > $null 输出空值的手动页面 名称 出空 提要 删除输出,而不是将其发送到控制台。 语法 输出Null[-inputObje

假设您有一个返回某些内容的方法或cmdlet,但您不想使用它,也不想输出它。我发现有两种方法:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null
你用什么?哪种方法更好/更干净?为什么?

还有cmdlet,您可以在管道中使用它,例如,
additem | Out Null

Do-Something > $null
输出空值的手动页面
名称
出空
提要
删除输出,而不是将其发送到控制台。
语法
输出Null[-inputObject][]
详细说明
Out-Null cmdlet将输出发送到Null,实际上是将其删除。
相关链接
输出打印机
外宾
出档
外线
违约
评论
有关详细信息,请键入:“get help Out Null-detailed”。
有关技术信息,请键入:“get help Out Null-full”。

<代码> > p>我会考虑使用类似的:

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
,因为很明显,输出不会被使用,会被丢弃。

我只是对我知道的四个选项做了一些测试

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
## 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
大约有0.3%的开销

附录2017-10-16:我最初忽略了另一个带有
Out Null
的选项,即使用
-inputObject
参数。使用此选项,开销似乎消失了,但语法不同:

Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})
现在我们来看一些使用简单的100对象管道的测试

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

的明确理由,我意识到这是一个古老的线程,但对于那些将@JasonMArcher的上述公认答案视为事实的人来说,我感到惊讶的是,它一直没有得到纠正。我们中的许多人多年来都知道,它实际上是管道增加了延迟,与是否Out Null无关。事实上,如果您运行下面的测试,您将很快看到,多年来我们一直认为它更快的[void]和$void=的“更快”转换实际上也同样慢,事实上在添加任何管道时都非常慢。换言之,只要你通过管道连接到任何东西,不使用out null的整个规则就会被扔进垃圾桶

Do-Something > $null
证明,以下列表中的最后3项测试。可怕的输出空值是32339.3792毫秒,但是等等——向[void]施放的速度要快多少?34121.9251毫秒?!?世界跆拳道联盟?在我的系统中,这些都是真实的,释放到虚空实际上要慢一些。=$null怎么样?34217.685毫秒…还是慢得要命!因此,正如最后三个简单测试所显示的,在许多情况下,当管道已经在使用时,Out Null实际上更快

那么,这是为什么?简单。它是而且一直是100%的一种幻觉,即管道输出到空是较慢的。然而,管道到任何东西都是比较慢的,我们不是已经通过基本逻辑知道了吗?我们可能不知道要慢多少,但如果您可以避免,这些测试肯定会告诉您使用管道的成本。而且,我们并不是100%错了,因为只有极少数情况下out null是邪恶的。什么时候添加时,Null是添加唯一的管道活动。换句话说,上面显示的像$(1..1000)| Out Null这样的简单命令的原因是正确的

如果您只需在上面的每个测试中为Out字符串添加一个额外的管道,那么#的变化将是根本性的(或者只是粘贴下面的管道),正如您自己所看到的,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

就我个人而言,我使用
。|Out Null
因为,正如其他人所评论的,与
相比,这看起来更像是一种“powershell”方法$空
[void]…
$null=…
利用了一个特定的函数,很容易被忽略,而其他方法则通过附加语法明确表示您打算放弃表达式的输出。因为
。|输出空值
…>$null
出现在表达式的末尾,我认为他们有效地传达了“把我们到目前为止所做的一切都拿走,扔掉”,此外,与放入
$null=
[void]相比,您可以更容易地注释它们,以便于调试(例如,
。#out null
在表达式之前,以确定执行后会发生什么

不过,让我们看一个不同的基准:不是执行每个选项所需的时间,而是找出每个选项的作用所需的时间。在与没有使用PowerShell甚至脚本编写经验的同事一起工作的环境中,我倾向于尝试以一种方式编写脚本,即几年后出现的甚至不懂他们所使用的语言的人可能会有机会了解它在做什么,因为他们可能正在使用