PowerShell में आउटपुट को अनदेखा करने का बेहतर (क्लीनर) तरीका क्या है? [बन्द है]


134

मान लीजिए कि आपके पास एक विधि या एक cmdlet है जो कुछ देता है, लेकिन आप इसका उपयोग नहीं करना चाहते हैं और आप इसे आउटपुट नहीं करना चाहते हैं। मुझे ये दो तरीके मिले:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

तुम क्या इस्तेमाल करते हो? कौन सा बेहतर / क्लीनर दृष्टिकोण है? क्यों?


1
[शून्य] संस्करण की तरह ... मेरे लिए अभी तक नहीं था, लेकिन मैं इसे याद रखने की कोशिश करूंगा।
मासिफ

जवाबों:


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

संपादित करें

स्टेपज की टिप्पणी के बाद, मैंने आउटपुट को ट्रेश करने के ओवरहेड को बेहतर ढंग से अलग करने के लिए पाइपलाइनों के साथ कुछ और परीक्षण करने का फैसला किया।

यहाँ एक साधारण 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से -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
मैं आम तौर पर उन चीजों के लिए वीओआईडी का उपयोग करता हूं जो एक भाषा लाइन का हिस्सा हैं, और बाहर से अशक्त अगर इसकी पहले से ही एक बड़ी लंबी पाइपलाइन किसी भी तरह
klumsy

25
Out-Nullशायद ओवरहेड है। लेकिन .. अगर एक वस्तु को Out-Null0.076 मिली सेकेंड तक पाइप किया जाए , तो यह अभी भी स्क्रिप्टिंग भाषा के लिए पूरी तरह से ठीक है :)
Stepj

1
मैं इसके साथ थोड़ा गड़बड़ कर रहा था, और मुझे आउट-नल -InputObject ($ (1..1000) | {$ $ -is [int]}) का उपयोग करके [शून्य] और $ null पर सर्वश्रेष्ठ प्रदर्शन मिलता है।
टोमोहुलक

1
अच्छा बिंदु, कि कोई ध्यान देने योग्य ओवरहेड लगता है।
जेसनम्रेचर

5
हालांकि, कुछ को पूरा करने के विभिन्न तरीकों की तुलना करने के लिए बेंचमार्क रखना हमेशा अच्छा होता है, आइए दूसरे निष्कर्ष को अनदेखा न करें जो यहां खींचे जा सकते हैं: जब तक आप मानों को त्यागने के लिए नहीं होते हैं सैकड़ों बार प्रदर्शन अंतर नगण्य होते हैं। और अगर यहाँ एक मिलीसेकंड या वास्तव में आपके लिए मायने रखता है, तो आपको संभवतः पहली जगह में पॉवरशेल का उपयोग नहीं करना चाहिए। इस संबंध में विकल्प रैंक के बारे में कोई निर्णय किए बिना, यह जरूरी नहीं है कि पठनीयता और व्यक्त करने वाले प्रोग्रामर इरादे जैसे अन्य गुणों के लिए गति का त्याग करना एक बुरी बात है।
BACON

22

मुझे लगता है कि यह एक पुराना धागा है, लेकिन जो @ जेसनमैकर के ऊपर दिए गए जवाब को तथ्य के रूप में स्वीकार कर रहे हैं, मुझे आश्चर्य है कि यह सही नहीं है कि हममें से कई लोग सालों से जानते हैं कि यह वास्तव में देरी को जोड़ने वाला पाइपलाइन है और ऐसा करने के लिए कुछ भी नहीं। यह आउट-नल है या नहीं। वास्तव में, यदि आप नीचे दिए गए परीक्षण चलाते हैं, तो आप जल्दी ही देखेंगे कि उसी "तेज" कास्टिंग [शून्य] और $ शून्य = के लिए, जो कि हम सभी वर्षों से सोच रहे थे कि यह तेजी से उपयोग हो रहा है, वास्तव में केवल धीमी गति से और वास्तव में बहुत कम है जब आप किसी भी पाइपलाइन को जोड़ दें। दूसरे शब्दों में, जैसे ही आप किसी चीज को पाइप करते हैं, आउट-नल का उपयोग नहीं करने का पूरा नियम कचरा में चला जाता है।

सबूत, नीचे दी गई सूची में अंतिम 3 परीक्षण। भयानक आउट-नल 32339.3792 मिलीसेकंड था, लेकिन प्रतीक्षा करें - कितनी तेजी से [शून्य] को कास्टिंग कर रहा था? 34121.9251 एमएस ?: WTF? ये मेरे सिस्टम पर असली #s हैं, VOID के लिए कास्टिंग वास्तव में धीमी थी। कैसे के बारे में = $ null? 34217.685ms ..... अभी भी friggin SLOWER! इसलिए, जैसा कि अंतिम तीन सरल परीक्षण दिखाते हैं, आउट-नल वास्तव में कई मामलों में तेजी से होता है जब पाइपलाइन पहले से उपयोग में है।

तो, यह क्यों है? सरल। यह हमेशा 100% मतिभ्रम था जो आउट-नल को पाइपिंग धीमी थी। हालांकि यह है कि कुछ भी करने के लिए PIPING धीमी है, और क्या हम पहले से ही यह नहीं जानते हैं कि बुनियादी तर्क के माध्यम से? हम सिर्फ HOW MUCH को धीमा नहीं जान सकते हैं, लेकिन ये परीक्षण निश्चित रूप से पाइपलाइन का उपयोग करने की लागत के बारे में एक कहानी बताते हैं यदि आप इससे बच सकते हैं। और, हम वास्तव में 100% गलत नहीं थे क्योंकि वास्तविक परिदृश्यों की बहुत कम संख्या है जहां आउट-नल बुराई है। कब? आउट-नल को जोड़ने पर केवल पाइप लाइन गतिविधि को जोड़ना है। दूसरे शब्दों में .... कारण $ (1.000) जैसी सरल आज्ञा | आउट-नल जैसा कि ऊपर दिखाया गया है सच दिखाया गया है।

यदि आप ऊपर दिए गए प्रत्येक परीक्षण में बस एक अतिरिक्त पाइप जोड़ते हैं, तो # मौलिक रूप से बदल जाते हैं (या बस नीचे वालों को चिपकाएँ) और जैसा कि आप स्वयं देख सकते हैं, आउट-नल वास्तव में कई मामलों में तेजी से बनता है:

$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 $GetProcessबनाम 5.656 सेकंड (लगभग 10x धीमा) के लिए 0.576 सेकंड मिलते हैं $GetProcess | Out-Null
BACON

हाय कॉलिन, आपके उत्तर के लिए धन्यवाद। मैंने आपके नमूने लिए, लेकिन सभी बैचों में [void]और फिर $nullभी इससे बेहतर प्रदर्शन किया | Out-Null। मुझे लगता है कि यह पाइपलाइन के कारण है और डेल्टा बाद के बैचों के साथ सिकुड़ता है, लेकिन मेरी मशीन पर Out-Nullकिसी भी बैच में तेजी से प्रदर्शन नहीं होता है।
Hinek

लेकिन निश्चित रूप से मुझे उन लोगों से सहमत होना होगा, जो तर्क देते हैं, कि प्रदर्शन सब कुछ नहीं है और पठनीयता भी कारक होनी चाहिए।
Hinek

@ हिनक आपकी टिप्पणी से आपको पता चलता है कि कॉलिन जो कह रहा था, उससे आप चूक गए। हाँ, [void]और $nullबेहतर प्रदर्शन करेंगे | Out-Nullकी वजह से - |Out-Null -InputObject (expression)तुलना के लिए प्रयास करें ।
जोनाथन गिल्बर्ट

19

वहाँ भी है Out-Null, cmdlet है, जो आप एक पाइप लाइन में उपयोग कर सकते हैं, उदाहरण के लिए Add-Item | 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".

जेसन के जवाब में छोटे बेंचमार्क टेस्ट के परिणामों के बारे में आप क्या सोचते हैं?
हाइनक

बहुत दिलचस्प, विशेष रूप से आउट-नल और अन्य तरीकों के बीच वास्तव में बहुत बड़ा अंतर। मुझे लगता है कि मैं तब भी स्विच करूंगा [void], जब आउट-नल समाधान अधिक "पॉवरशेलिश" दिखता है।
ओकासो प्रोटल

मुझे अभी भी यकीन नहीं है, मेरा पसंदीदा तरीका क्या है। यहां तक ​​कि यह बहुत बड़ा अंतर शायद ही महत्वपूर्ण लगता है क्योंकि स्टीज ने पहले ही टिप्पणी की थी।
हिनक

2
@ हाइनक [void]बहुत स्पष्ट दिखता है (जैसा कि मैंने कहा था कि कोई शक्तियां नहीं हैं), आप लाइन की शुरुआत में देखेंगे कि इस लाइन में कोई आउटपुट नहीं है। तो यह एक और फायदा है, और यदि आप बड़े लूप में आउट-नल करते हैं, तो प्रदर्शन एक मुद्दा हो सकता है;)
ओकासो प्रोटल

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क्योंकि, जैसा कि दूसरों ने टिप्पणी की है, जो कि ... > $nullऔर की तुलना में अधिक "पॉवरशेलिश" दृष्टिकोण की तरह दिखता है [void] ...$null = ...एक विशिष्ट स्वचालित चर का शोषण कर रहा है और इसे अनदेखा करना आसान हो सकता है, जबकि अन्य विधियाँ अतिरिक्त वाक्यविन्यास के साथ यह स्पष्ट करती हैं कि आप एक अभिव्यक्ति के उत्पादन को छोड़ने का इरादा रखते हैं। क्योंकि ... | Out-Nullऔर ... > $nullअभिव्यक्ति के अंत में मुझे लगता है कि वे प्रभावी ढंग से संवाद करते हैं "हमने जो कुछ भी किया है उसे इस बिंदु तक ले जाएं और इसे फेंक दें", साथ ही आप उन्हें डीबगिंग उद्देश्यों (जैसे ... # | Out-Null) के लिए आसान लगा $null =सकते हैं , जैसे कि डालने या [void] पहले की तुलना में। यह निर्धारित करने के लिए कि इसे निष्पादित करने के बाद क्या होता है।

आइए एक अलग बेंचमार्क देखें, हालांकि: प्रत्येक विकल्प को निष्पादित करने में जितना समय लगता है, उतना नहीं है, लेकिन प्रत्येक विकल्प क्या करता है, यह जानने में समय लगता है । उन सहयोगियों के साथ वातावरण में काम करने के बाद, जो पावरशेल के साथ अनुभवी नहीं थे या यहां तक ​​कि स्क्रिप्टिंग भी नहीं करते थे, मैं अपनी स्क्रिप्ट को इस तरह से लिखने की कोशिश करता हूं कि सालों बाद आने वाले किसी व्यक्ति को यह भी समझ में न आए कि जिस भाषा को वे देख रहे हैं वह एक तरह से हो सकती है पता लगाने का मौका है कि यह क्या कर रहा है क्योंकि वे समर्थन करने या इसे बदलने की स्थिति में हो सकते हैं। यह मेरे लिए अब तक दूसरों पर एक विधि का उपयोग करने के कारण के रूप में कभी नहीं हुआ है, लेकिन कल्पना करें कि आप उस स्थिति में हैं और आप helpयह जानने की कोशिश करने के लिए कमांड या अपने पसंदीदा खोज इंजन का उपयोग करते हैं कि क्याOut-Nullकर देता है। आपको तुरंत एक उपयोगी परिणाम मिलता है, है ना? अब इसके साथ [void]और करने की कोशिश करें $null =। इतना आसान नहीं है, है ना?

दी गई, किसी मान के आउटपुट को दबाने से स्क्रिप्ट के समग्र तर्क को समझने की तुलना में एक बहुत ही मामूली विस्तार होता है, और आप केवल एक के लिए अच्छा कोड लिखने की अपनी क्षमता का व्यापार करने से पहले अपने कोड को "बहुत नीचे" करने की कोशिश कर सकते हैं। नौसिखिए पढ़ने की क्षमता ... इतना अच्छा कोड नहीं। मेरी बात है, यह है कि कुछ है जो PowerShell में धाराप्रवाह हैं के साथ भी परिचित नहीं हैं संभव है [void], $null =, आदि, और सिर्फ इसलिए कि उन तेजी से निष्पादित या प्रकार के लिए कम कीस्ट्रोक्स लग सकता है, इसका मतलब यह नहीं है कि वे क्या करने के लिए सबसे अच्छा तरीका हो आप क्या करने की कोशिश कर रहे हैं, और सिर्फ इसलिए कि एक भाषा आपको विचित्र वाक्यविन्यास देती है इसका मतलब यह नहीं है कि आपको इसका उपयोग कुछ स्पष्ट और बेहतर-ज्ञात के बजाय करना चाहिए। *

* मैं मान रहा हूँ कि Out-Nullस्पष्ट और अच्छी तरह से जाना जाता है, जो मैं नहीं जानता $true। जो भी विकल्प आपको लगता है कि भविष्य के पाठकों और आपके कोड के संपादक (स्वयं शामिल हैं) के लिए सबसे स्पष्ट और सुलभ है, भले ही समय-समय पर या समय-समय पर निष्पादित होने की परवाह किए बिना, वह विकल्प है जो मैं आपको उपयोग करने की सिफारिश कर रहा हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.