Каков лучший (более чистый) способ игнорировать вывод в PowerShell?
допустим, у вас есть метод или командлет, который возвращает что-то, но вы не хотите его использовать и не хотите его выводить. Я нашел эти два способа:
Add-Item > $null
[void]Add-Item
Add-Item | Out-Null
что вы используете? Какой подход лучше / чище? Зачем?
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 является наиболее ясным и доступным для будущих читателей и редакторов вашего кода (включая вас), независимо от времени ввода или времени выполнения, это вариант, который я рекомендую вам использовать.