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


134

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

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

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


1
[void] 버전과 같은 ... 아직까지는 없었지만 기억하려고 노력하겠습니다.
Massif

답변:


181

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

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.


1
나는 일반적으로 랭귀지 라인의 일부인 것들에 대해 VOID를 사용하고, 이미 큰 파이프 라인
이라면

25
Out-Null아마도 오버 헤드 일 수 있습니다. 그러나 .. 하나의 객체를 Out-Null0.076 밀리 초로 파이핑하면 스크립트 언어로는 여전히 완벽합니다 :)
stej

1
나는 이것을 조금 엉망으로 만들었고 Out-Null -InputObject ($ (1..1000) |? {$ _ -is [int]})를 사용하여 [void] 및> $ null보다 최상의 성능을 얻었습니다.
tomohulk

1
좋은 점은 눈에 띄는 오버 헤드가없는 것 같습니다.
JasonMArcher

5
무언가를 달성하는 여러 가지 방법을 비교하기 위해 벤치 마크를 갖는 것이 항상 좋지만, 여기에서 도출 할 수있는 다른 결론을 간과하지 마십시오. 수십만 번 값을 버릴 필요가 없다면 성능 차이는 무시할 수 있습니다. 그리고 여기 또는 거기에 밀리 초가 중요하다면 우선 PowerShell을 사용하지 않아야합니다. 이러한 점에서 옵션의 순위를 결정하지 않으면 가독성 및 프로그래머 의도 표현과 같은 다른 특성을 위해 속도를 희생하는 것이 반드시 나쁜 것은 아닙니다.
BACON

22

나는 이것이 오래된 실이라는 것을 알고 있지만, @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

이 중요한 점을 +1했습니다. 실제로 Out-Null파이프 라인 을 사용 하는 사람이 전혀 없어서 파이프 라인의 오버 헤드를 표시하는 가장 좋은 방법은 파이프 라인을 Out-Null사용하거나 사용하지 않고 호출 하는 것입니다. 내 시스템에서 10,000 회 반복하면에 대해 Out-Null -InputObject $GetProcess5.656 초 (약 10 배 느림) 동안 0.576 초가 발생 합니다 $GetProcess | Out-Null.
BACON

콜린 안녕, 답변 주셔서 감사합니다. 샘플을 실행했지만 모든 배치 [void]에서 $null여전히보다 나은 성능을 보였습니다 | Out-Null. 나는 이것이 파이프 라인 때문이며 델타는 나중 배치로 축소되지만 내 컴퓨터 Out-Null에서는 배치에서 더 빨리 수행되지 않습니다.
Hinek

그러나 물론 성능이 모든 것이 아니며 가독성도 고려해야한다고 주장하는 사람들과 동의해야합니다.
Hinek

@Hinek 귀하의 의견에 따르면 Collin이 말한 요점을 놓쳤습니다. 예, [void]그리고 $null보다 더 수행합니다 | Out-Null- 때문에의 |. Out-Null -InputObject (expression)비교해 보십시오 .
조나단 길버트

19

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".

Jason의 답변에서 작은 벤치 마크 테스트의 결과에 대해 어떻게 생각하십니까?
Hinek

Out-Null과 다른 방법의 차이점은 매우 흥미 롭습니다. [void]Out-Null 솔루션이 더 "파워 쉘 리쉬"해 보이지만 전환 할 것이라고 생각 합니다.
Ocaso Protal

여전히 확실하지 않습니다. 선호하는 방법은 무엇입니까? stej가 이미 언급 했듯이이 큰 차이조차 거의 중요하지 않습니다.
Hinek

2
@Hinek [void]은 매우 명확하게 보입니다 (내가 말한 것처럼 파워 쉘이 아닙니다). 선의 시작 부분 에이 줄에 출력이 없음을 알 수 있습니다. 따라서 이것은 또 다른 장점이며, 큰 루프에서 Null을 수행하는 경우 성능이 문제가 될 수 있습니다.)
Ocaso Protal

11

나는 다음과 같은 것을 사용하는 것을 고려할 것이다 :

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


2

개인적으로, 나는 ... | 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. 어느 옵션 깨끗한 미래의 리더와 코드의 편집자에 가장 접근 (자신을 포함)을 느낄 관계없이 시간에 형 내가 사용 추천 해요 옵션들 중 하나 또는 타임 - 투 - 실행.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.