Каков лучший (более чистый) способ игнорировать вывод в PowerShell?


допустим, у вас есть метод или командлет, который возвращает что-то, но вы не хотите его использовать и не хотите его выводить. Я нашел эти два способа:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

что вы используете? Какой подход лучше / чище? Зачем?

5 101

5 ответов:

я только что сделал некоторые тесты из четырех вариантов,которые я знаю.

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

Edit

после комментария стэя снова, я решил сделать еще несколько тестов с трубопроводами, чтобы лучше изолировать накладные расходы на разгром выхода.

вот некоторые тесты с простым конвейером объектов 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 использование

есть еще 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".

Я хотел бы использовать что-то вроде:

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 ведь совершенно ясно, что выход не будет использоваться и выкидывается.

Я понимаю, что это старый поток, но для тех, кто принимает принятый ответ @JasonMArcher выше как факт, я удивлен, что он не был исправлен многие из нас знали в течение многих лет, на самом деле это конвейер, добавляющий задержку, и ничего общего с тем, является ли он нулевым или нет. На самом деле, если вы запустите тесты ниже, вы быстро увидите, что то же самое "более быстрое" приведение к [void] и $void= что в течение многих лет мы все думали, что это было быстрее, на самом деле так же медленно и на самом деле очень медленно, когда вы добавляете любой конвейер вообще. Другими словами, как только вы подключаетесь к чему-либо, все правило не использовать out-null отправляется в корзину.

доказательство, последние 3 теста в списке ниже. Ужасный Out-null был 32339.3792 миллисекунды, но подождите - насколько быстрее было приведение к [void]? 34121.9251 МС?!? WTF? Это реальные #s в моей системе, приведение к пустоте было на самом деле медленнее. Как насчет =$null? 34217.685 МС.....все еще чертовски медленнее! Итак, как показывают последние три простых теста, Out-Null на самом деле быстрее во многих случаях, когда конвейер уже используется.

Так почему же это? Простой. Это и всегда было 100% галлюцинацией, что трубопровод к Out-Null был медленнее. Это, однако, что трубопровод к чему-либо медленнее, и разве мы уже не знаем, что через базовую логику? Мы просто не знаем, насколько медленнее, но эти тесты наверняка расскажут историю о стоимости использования трубопровода, если вы можете этого избежать. И мы не были на 100% неправы, потому что существует очень небольшое количество истинных сценариев, где out-null является злом. Когда? При добавлении Out-Null добавляется единственное действие конвейера. Иначе говоря....причина простая команда вроде $(1..1000) / Out-Null, как показано выше, показал true.

Если вы просто добавляете дополнительный канал к 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

лично я использую ... | Out-Null потому что, как прокомментировали другие, это похоже на более "PowerShellish" подход по сравнению с ... > $null и [void] .... $null = ... использует специфические автоматическая переменная и может быть легко упустить из виду, в то время как другие методы делают это очевидным с дополнительным синтаксисом, что вы намерены отказаться от вывода выражения. Потому что ... | Out-Null и ... > $null в конце выражения, я думаю, что они эффективно "взять все мы сделали до этого момента и выбросить его", плюс вы можете прокомментировать их легче для целей отладки (например,... # | Out-Null), по сравнению с putting $null = или [void]до выражение для определения того, что происходит после его выполнением.

давайте посмотрим на другой тест, хотя: не количество времени, необходимое для выполнения каждой опции, но количество времени, необходимое для выяснить, что каждый вариант делает. Работая в окружение с коллегами, которые не имели опыта работы с PowerShell или даже сценариев на всех, я, как правило, пытаются писать свои сценарии таким образом, что кто-то приходит через несколько лет, которые могут даже не понимать язык, на который они смотрят, может иметь шанс на борьбу с выяснением того, что он делает, так как они могут быть в состоянии поддерживать или заменять его. Это никогда не приходило мне в голову как причина использовать один метод над другими до сих пор, но представьте, что вы находитесь в таком положении и вы используете help команда или ваша любимая поисковая система, чтобы попытаться выяснить, что Out-Null делает. Вы получаете полезный результат сразу же, не так ли? Теперь попробуйте сделать то же самое с [void] и $null =. Не так-то просто, правда?

конечно, подавление вывода значения-довольно незначительная деталь по сравнению с пониманием общей логики сценария, и вы можете только попытаться "заглушить" свой код так много, прежде чем вы торгуете своей способностью писать хороший код для способности новичка читать...не очень хороший код. Я хочу сказать, возможно, что некоторые, кто свободно владеет PowerShell, даже не знакомы с [void],$null = и т. д. и только потому, что они могут выполняться быстрее или занимать меньше нажатий клавиш для ввода, не означает, что они лучший способ сделать то, что вы пытаетесь сделать, и только потому, что язык дает вам причудливый синтаксис, не означает, что вы должны использовать его вместо чего-то более ясного и более известного.*

* я предполагаю, что Out-Null - это понятно и хорошо известно, что я не знаю $true. Какой бы вариант вы feel является наиболее ясным и доступным для будущих читателей и редакторов вашего кода (включая вас), независимо от времени ввода или времени выполнения, это вариант, который я рекомендую вам использовать.