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

Hin*_*nek 121 powershell null void

假设您有一个返回某些内容的方法或cmdlet,但您不想使用它而您不想输出它.我找到了这两种方式:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null
Run Code Online (Sandbox Code Playgroud)

你用什么?哪种更好/更清洁?为什么?

Jas*_*her 164

我刚刚对我所知道的四个选项进行了一些测试.

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
Run Code Online (Sandbox Code Playgroud)

所以我建议你使用任何东西,但Out-Null由于开销.对我来说,下一个重要的事情是可读性.我有点像重定向到$null$null自己一样.我喜欢使用[Void],但在浏览代码或新用户时可能无法理解.

我想我稍微倾向于将输出重定向到$null.

Do-Something > $null
Run Code Online (Sandbox Code Playgroud)

编辑

在再次发表评论之后,我决定用管道进行更多测试,以更好地隔离破坏输出的开销.

以下是一些简单的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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Out-Null开销约为60%,开销> $null约为0.3%.

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

Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})
Run Code Online (Sandbox Code Playgroud)

现在用一些简单的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
Run Code Online (Sandbox Code Playgroud)

这里又有Out-Null大约60%的开销.虽然> $null开销约为4%.这里的数字从测试到测试有点不同(我每次运行约5次并选择中间地面).但我认为它显示了不使用的明确理由Out-Null.

  • `Out-Null`可能是开销.但是..如果将一个对象传递给'Out-Null` 0.076毫秒,那么对于脚本语言来说它仍然完美无缺:) (20认同)
  • 尽管拥有基准来比较完成某项工作的不同方式总是很有益的,但我们不要忽视这里可以得出的另一个结论:除非您必须舍弃数十万次的值,否则性能差异可以忽略不计。如果在这里或那里真正需要毫秒,那么您一开始就不应该使用PowerShell。如果不对选项在这些方面的排名做出任何判断,那么牺牲速度来提高其他质量(例如可读性和表达程序员的意图)并不一定是一件坏事。 (3认同)

Oca*_*tal 19

还有Out-Nullcmdlet,例如,您可以在管道中使用它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".
Run Code Online (Sandbox Code Playgroud)

  • @Hinek` [void]`看起来非常清楚(不像我所说的那样,是无意义的),你会在行的开头看到这一行没有输出.所以这是另一个优势,如果你在大循环中进行Out-Null,性能可能是一个问题;) (2认同)

Col*_*fin 18

我意识到这是一个老话题,但对于那些将@ JasonMArcher接受的答案作为事实的人,我很惊讶它没有得到纠正我们许多人多年来已经知道它实际上是PIPELINE添加延迟而没有关于是否它是Out-Null还是No.事实上,如果你运行下面的测试,你会很快看到同样的"更快"的转换为[void]和$ void =多年来我们都认为它更快,实际上只是很慢,实际上非常慢你添加任何流水线无论如何.换句话说,只要你管道到任何东西,不使用out-null的整个规则就会进入垃圾箱.

证明,下面列表中的最后3个测试.可怕的Out-null是32339.3792毫秒,但等待 - 加速到[void]的速度有多快?34121.9251 ms?!?WTF?这些是我系统上的REAL #s,转换为VOID实际上是SLOWER.= $ null怎么样?34217.685ms .....还是friggin SLOWER!因此,正如最后三个简单测试所示,在管道已经投入使用的情况下,Out-Null实际上更快.

那么,这是为什么呢?简单.对Out-Null的管道来说,它总是100%幻觉.然而,PIPING TO ANYTHING速度较慢,我们是不是已经知道通过基本逻辑?我们可能不知道这么慢,但这些测试确实讲述了如果你可以避免使用管道的成本.并且,我们并没有真正100%错误,因为有一小部分真实场景,其中out-null是邪恶的.什么时候?添加Out-Null时添加ONLY管道活动.换句话说....之所以像$(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
Run Code Online (Sandbox Code Playgroud)

  • +1 提出这一重要观点。事实上,并没有强迫任何人在管道中使用`Out-Null`,所以显示管道开销的最好方法是在有和没有它的情况下调用`Out-Null`。在我的系统上,对于 10,000 次迭代,`Out-Null -InputObject $GetProcess` 为 0.576 秒,而`$GetProcess | 为 5.656 秒(慢了近 10 倍)。出空`。 (2认同)

ste*_*tej 11

我会考虑使用类似的东西:

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

$a.Add不返回输出- 适用于所有$a.Add方法调用.否则,您需要[void]在每次通话之前进行前置.

在简单的情况下,我会选择,[void]$a.Add因为很明显输出将不会被使用并被丢弃.


BAC*_*CON 10

就我个人而言,我使用它是因为,正如其他人评论的那样,与和... | Out-Null相比,这看起来更像是“PowerShellish”方法。 正在利用特定的自动变量,并且很容易被忽视,而其他方法则通过附加语法使您明显地表明您打算丢弃表达式的输出。因为和出现在表达式的末尾,我认为它们有效地传达了“将我们到目前为止所做的一切都扔掉”,而且与 put或before相比,您可以更轻松地注释掉它们以进行调试(例如)表达式来确定执行后会发生什么。... > $null[void] ...$null = ...... | Out-Null... > $null... # | Out-Null$null =[void]

不过,让我们看一下不同的基准:不是执行每个选项所需的时间,而是弄清楚每个选项的作用所需的时间。在与没有使用 PowerShell 甚至根本没有脚本编写经验的同事一起工作的环境中,我倾向于尝试以一种方式编写脚本,以便多年后出现的甚至可能不理解他们正在查看的语言的人也可以因为他们可能必须支持或替换它,所以要努力弄清楚它在做什么。到目前为止,我从未想到过使用一种方法而不是其他方法的理由,但想象一下您处于那个位置,并且您使用该help命令或您最喜欢的搜索引擎来尝试找出其作用Out-Null。您立即得到有用的结果,对吗?[void]现在尝试对和执行同样的操作$null =。没那么容易,不是吗?

诚然,与理解脚本的整体逻辑相比,抑制值的输出是一个相当小的细节,并且在你用编写良好代码的能力来换取一个好的代码之前,你只能尝试“简化”你的代码。新手阅读不太好的代码的能力。我的观点是,一些精通 PowerShell 的人可能甚至不熟悉[void]$null =等,并且仅仅因为这些可能执行得更快或需要更少的击键来键入,并不意味着它们是最好的方法你想要做什么,并且仅仅因为一种语言给你提供了古怪的语法并不意味着你应该使用它而不是更清晰和更广为人知的东西。*

*我认为这Out-Null是明确且众所周知的,但我不知道这一点$true无论您认为哪个选项对未来的代码读者和编辑者(包括您自己)来说最清晰且最容易访问,无论输入时间或执行时间如何,我都建议您使用该选项。