[powershell] PowerShell에서 출력을 무시하는 더 나은 (깨끗한) 방법은 무엇입니까? [닫은]

무언가를 반환하는 메서드 나 cmdlet이 있지만 사용하지 않고 출력하고 싶지 않다고 가정 해 봅시다. 이 두 가지 방법을 찾았습니다.

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

무엇을 사용하십니까? 더 나은 / 깨끗한 접근 방법은 무엇입니까? 왜?



답변

방금 내가 알고있는 네 가지 옵션에 대한 테스트를했습니다.

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오버 헤드 > $null는 약 60 %이고 오버 헤드 는 약 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.


답변

나는 이것이 오래된 실이라는 것을 알고 있지만, @JasonMArcher의 위의 대답을 사실로 받아들이는 사람들에게는 실제로 많은 사람들이 수년간 알려지지 않은 사실에 놀랐습니다. 실제로 PIPELINE이 지연을 추가하고 있는지 여부와 관계가 없습니다. Null인지 여부입니다. 실제로, 아래 테스트를 실행하면 [void]와 $ void =에 동일한 “빠른”캐스팅이 수년 동안 우리 모두가 더 빠르다고 생각했지만 실제로는 느리고 실제로는 매우 느리다는 것을 알 수 있습니다. 파이프 라인을 추가하십시오. 다시 말해서, 파이프를 사용하면 널 (null)을 사용하지 않는 전체 규칙이 휴지통에 들어갑니다.

증명, 아래 목록의 마지막 3 가지 테스트. 끔찍한 Out-null은 32339.3792 밀리 초이지만 [void]로 캐스팅하는 속도는 얼마나 빠릅니까? 34121.9251 ms?!? WTF? 이들은 내 시스템에서 실제 #이며, VOID로 캐스팅하는 것은 실제로 느 렸습니다. = $ null은 어떻습니까? 34217.685ms ….. 여전히 friggin SLOWER! 따라서 마지막 세 가지 간단한 테스트에서 알 수 있듯이 파이프 라인이 이미 사용중인 경우 대부분의 경우 Out-Null이 더 빠릅니다.

왜 이럴까요? 단순한. Out-Null 로의 배관이 느리다는 것은 항상 100 % 환각이었습니다. 그러나 PIPING TO ANYTHING은 느리고 기본 논리를 통해 이미 알고 있지 않습니까? 우리는 속도를 얼마나 느리게 알지 못했을 수도 있지만 이러한 테스트를 통해 파이프 라인을 피할 수 있다면 사용 비용에 대한 이야기를들 수 있습니다. 그리고 널 (null) 널이 악한 경우에 매우 적은 수의 실제 시나리오가 있기 때문에 우리는 실제로 100 % 잘못이 아니 었습니다. 언제? 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


답변

Out-Null파이프 라인에서 사용할 수 있는 cmdlet 도 있습니다 (예 🙂 Add-Item | Out-Null.

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출력이 사용되지 않고 버려 질 것이 분명하기 때문에 함께 갈 것입니다 .


답변

개인적으로, 나는 ... | Out-Null다른 사람들이 언급했듯이 ... > $nulland 보다 더 “PowerShellish”접근 방식처럼 보이기 때문에 사용 [void] ...합니다. $null = ...는 특정 자동 변수를 활용하고 간과하기 쉬운 반면 다른 방법은 식의 출력을 삭제하려는 추가 구문을 사용하여 명확하게 만듭니다. 때문에 ... | Out-Null... > $null표현의 끝에 와서 내가 효과적으로 “우리가이 시점까지 수행 한 모든을 멀리 던져”, 플러스 (예 : 디버깅을 위해 그들을 쉽게 주석 처리 의사 소통을 생각한다 ... # | Out-Null), 퍼팅에 비해 $null =또는 [void] 이전 실행 발생하는 상황을 판별하는 표현식

각 옵션을 실행하는 데 걸리는 시간이 아니라 각 옵션이 수행하는 작업을 파악 하는 데 걸리는 시간은 다른 벤치 마크를 살펴 보겠습니다 . PowerShell을 경험하지 않았거나 전혀 스크립팅을하지 않은 동료와의 환경에서 작업 한 결과, 몇 년 후 누군가가보고있는 언어를 이해할 수없는 방식으로 스크립트를 작성하려고합니다. 지원하거나 교체해야 할 위치에있을 수 있으므로 수행중인 작업을 파악할 수있는 기회. 이것은 지금까지 다른 방법보다 한 가지 방법을 사용하는 이유로 결코 발생하지 않았지만 그 위치에 있고 help명령이나 좋아하는 검색 엔진을 사용하여Out-Null그렇습니다. 유용한 결과를 즉시 얻을 수 있습니다. 이제와 동일한 작업을 수행하려고 [void]하고 $null =. 그렇게 쉽지 않습니까?

물론, 값의 출력을 억제하는 것은 스크립트의 전반적인 논리를 이해하는 것과 비교할 때 아주 사소한 세부 사항이며, 좋은 코드를 작성하는 능력을 교환하기 전에 코드를 너무 많이 “어지럽게”시도 할 수 있습니다. 초보자가 읽을 수없는 코드를 읽을 수있는 능력. 내 요점은 PowerShell에 능숙한 일부 사용자가 , 등에 익숙하지 않을 수도 있으며 [void], $null =더 빨리 실행하거나 키 입력을 줄이려고한다고해서 이것이 가장 좋은 방법은 아니라는 것입니다 언어가 기발한 구문을 제공한다고해서 더 명확하고 잘 알려진 것 대신 언어를 사용해야한다는 의미는 아닙니다. *

* 나는 그것이 Out-Null명확하고 잘 알려져 있다고 생각 합니다 $true. 어느 옵션 깨끗한 미래의 리더와 코드의 편집자에 가장 접근 (자신을 포함)을 느낄 관계없이 시간에 형 내가 사용 추천 해요 옵션들 중 하나 또는 타임 – 투 – 실행.


답변