2010-12-05 21 views
18

में $ null को कैसे संभालना है मेरे पास अक्सर मेरे पावरशेल कोड में निम्न स्थिति होती है: मेरे पास कोई फ़ंक्शन या प्रॉपर्टी है जो ऑब्जेक्ट्स का संग्रह देता है, या $null। यदि आप परिणामों को पाइपलाइन में दबाते हैं, तो आप पाइपलाइन में एक तत्व भी संभालते हैं यदि $null एकमात्र तत्व है।पाइपलाइन

उदाहरण:

$Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" } 

अगर कोई सुविधाओं ($ Project.Features रिटर्न $ नल) कर रहे हैं, आप के साथ एक पंक्ति देखेंगे "सुविधा नाम:"।

if ($Project.Features -ne $null) 
{ 
    $Project.Features | Foreach-Object { Write-Host "Feature name: $($_.Name)" } 
} 

या

$Project.Features | Where-Object {$_ -ne $null) | Foreach-Object { 
    Write-Host "Feature name: $($_.Name)" 
} 

या

$Project.Features | Foreach-Object { 
    if ($_ -ne $null) { 
    Write-Host "Feature name: $($_.Name)" } 
    } 
} 

लेकिन असल में मैं इन तरीकों से किसी को पसंद नहीं है, लेकिन क्या करना:

मैं इस को हल करने के तीन तरीके को देखने के आप सबसे अच्छा दृष्टिकोण के रूप में देखते हैं?

उत्तर

25

मुझे नहीं लगता कि कोई भी इस तथ्य को पसंद करता है कि दोनों "foreach ($ n $ null) {}" और "$ null | foreach-object {}" एक बार फिर से सक्रिय हो जाते हैं। दुर्भाग्य से आपके द्वारा प्रदर्शित किए गए तरीकों से ऐसा करने का कोई और तरीका नहीं है। आप pithier हो सकता है:

filter Skip-Null { $_|?{ $_ } } 
:

$null | ?{$_} | % { ... } 

?{$_} आशुलिपि where-object {$_ -ne $null}$null के रूप में एक बूलियन अभिव्यक्ति के रूप में मूल्यांकन के लिए मैं एक फिल्टर इस तरह अपने प्रोफाइल में परिभाषित किया है $false

माना जाएगा है

उपयोग:

$null | skip-null | foreach { ... } 

एक फ़िल्टर फ़ंक्शन के समान होता है, डिफ़ॉल्ट ब्लॉक को छोड़कर प्रक्रिया {} समाप्त नहीं होती है {}।

अद्यतन: PowerShell 3.0, $null के रूप में संग्रह के रूप में अब पुन: प्रयोज्य नहीं है। वाह!

PS> function Empty { $null } 
PS> Empty | %{'hi'} 
hi 

PS> function Empty { @() } 
PS> Empty | %{'hi'} 

अन्यथा, क्या Oisin पता चलता है, हालांकि मैं एक मामूली सुझाव के साथ जाना:

+5

संक्षिप्त आशुलिपि के साथ समस्या यह है कि यह कुछ भी है कि coerces को अस्वीकार कर देंगे है 'झूठी' में, जिसमें '0',' "" ',' @() ',' @ (0) ', जैसी चीजें शामिल हैं ... मैं शायद 'Skip-null' को वास्तव में केवल $ $ छोड़ने की अपेक्षा करता हूं null'। मुझे पता है कि इस प्रश्न के संदर्भ में परिणाम एक जैसा है, लेकिन एक फिल्टर के लिए जो कहीं और इस्तेमाल किया जा सकता है ... – Joey

+0

@joey अच्छा बिंदु। – x0n

+0

दुख की बात है '@() |? {$ False}' अभी भी खाली सूची लौटने की बजाय $ null लौटाता है – ekkis

12

आप अपने कार्य को संशोधित कर सकते हैं -Oisin, यह $ अशक्त के बजाय एक खाली संग्रह/सरणी वापसी है tweak:

filter Skip-Null { $_|?{ $_ -ne $null } } 

अन्यथा यह भी फिल्टर करेगा 0 और $false

अपडेट 4-30-2012: यह समस्या PowerShell v3 में तय की गई है। वी 3 एक स्केलर $ शून्य मूल्य पर फिर से नहीं होगा।

+0

मैं केवल एक जवाब क्यों स्वीकार नहीं कर सकता! वे दोनों महान हैं, धन्यवाद दोस्तों! मैंने ओसीन को "जवाब" दिया, कीथ के पास पहले से ही सबसे अधिक बिंदु है :-) –

+0

जब आप पोस्ट किए जाने के लगभग 17 महीने बाद इसे संपादित करते हैं तो मुझे इस जवाब को देखने के लिए क्या संभावनाएं हैं? क्या इसकी गणना करने के लिए कोई cmdlet है? – BACON

+0

@BACON यह निश्चित रूप से संयोग नहीं है। मैंने अपने एसओ इनबॉक्स के माध्यम से देखा कि आपने मेरे उत्तरों में से एक पर टिप्पणी पोस्ट की है। :-) बस सोचा कि यह इंगित करना अच्छा होगा कि यह V3 में कोई मुद्दा नहीं है। –

2

कीथ के जवाब देने के लिए एक त्वरित टिप्पणी यह ​​

व्यक्तिगत रूप से, मैं कुछ भी नहीं वापसी होगी पूरा करने के लिए। यह समझ में आता है:

PS> function Empty { if ('a' -eq 'b') { 'equal' } } 
PS> Empty | % { write-host result is $_ } 

लेकिन अब आप समस्याओं में हैं अगर आप एक चर के लिए Empty से परिणाम में निर्दिष्ट करें:

PS> $v = Empty 
PS> $v | % { write-host result is $_ } 

एक छोटे से यह काम करने के लिए चाल है।

PS> $v = @(Empty) 
PS> $v | % { write-host result is $_ } 
PS> $v.GetType() 
IsPublic IsSerial Name  BaseType 
-------- -------- ----  -------- 
True  True  Object[] System.Array 
PS> $v.Length 
0 
+1

यह दृष्टिकोण मैं आज उपयोग करता हूं * यदि * मैं परिभाषा को नियंत्रित नहीं करता आदेश बुलाया जा रहा है। अन्यथा मैं एक खाली सरणी लौटाता हूं यदि फ़ंक्शन मानदंड कई आइटम लौटाता है जैसे कि मैं इसके बारे में सोचता हूं - @() में लपेटने के लिए भूलने में बहुत बार बारिश हुई है। :-) –

+0

@ केथ, मुझे लगता है कि आपने इस मुश्किल व्यवहार के बारे में महान लेख लिखा है। आप इसे यहां लिंक कर सकते हैं, दूसरों को इसे पढ़ना चाहिए, निश्चित रूप से;) – stej

2

एक और संभावना है:: बस इस तरह की एक सरणी के रूप में Empty से परिणाम लपेट

$objects | Foreach-Object -Begin{If($_ -eq $null){continue}} -Process {do your stuff here} 

अधिक जानकारी about_Continue में

संबंधित मुद्दे