2009-12-01 3 views
9
# array 
C:\> (1,2,3).count 
3 
C:\> (1,2,3 | measure).count 
3 

# hashtable 
C:\> @{1=1; 2=2; 3=3}.count 
3 
C:\> (@{1=1; 2=2; 3=3} | measure).count 
1 

# array returned from function 
C:\> function UnrollMe { $args } 
C:\> (UnrollMe a,b,c).count 
3 
C:\> (UnrollMe a,b,c | measure).count 
1 
C:\> (1,2,3).gettype() -eq (UnrollMe a,b,c).gettype() 
True 

हैशटेबल्स के साथ विसंगति fairly well known है, हालांकि official documentation केवल इसे विशिष्ट रूप से उल्लेख करता है (उदाहरण के माध्यम से)।क्या निर्धारित करता है कि पावरहेल पाइपलाइन संग्रह को अनलॉक कर देगी या नहीं?

हालांकि, कार्यों के साथ समस्या मेरे लिए खबर है। मैं बहुत शर्मिंदा हूं, इससे पहले कि उसने मुझे पहले काट नहीं दिया है। क्या कोई मार्गदर्शक सिद्धांत है जिसे हम अनुयायियों का पालन कर सकते हैं? मुझे पता है कि सी # में cmdlets लिखते समय overload of WriteObject है जहां आप स्पष्ट रूप से गणना को नियंत्रित कर सकते हैं, लेकिन AFAIK पॉश भाषा में ऐसा कोई भी निर्माण नहीं है। जैसा कि अंतिम उदाहरण दिखाता है, पोश दुभाषिया का मानना ​​है कि पाइप किए जाने वाले वस्तुओं के प्रकार में कोई अंतर नहीं है। मुझे संदेह है कि हुड के नीचे कुछ ऑब्जेक्ट बनाम पीएसओब्जेक्ट अजीबता हो सकती है, लेकिन जब आप शुद्ध पोश लिख रहे हैं और स्क्रिप्ट भाषा को "बस काम" करने की उम्मीद है तो इसका बहुत कम उपयोग होता है।

/संपादित करें/

कीथ का कहना है कि मेरे उदाहरण में, मैं एक एकल स्ट्रिंग [] तर्क में नहीं बल्कि 3 स्ट्रिंग तर्क से गुजर रहा हूँ सही है। दूसरे शब्दों में, कारण मापन-ऑब्जेक्ट का कारण है कि गणना = 1 है क्योंकि यह एक सरणी-ऑफ-एरे देख रहा है जिसका पहला तत्व @ ("ए", "बी", "सी") है। काफी उचित। यह ज्ञान आप कई तरीकों से समस्या के समाधान के लिए अनुमति देता है:

# stick to single objects 
C:\> (UnrollMe a b c | measure).count 
3 

# rewrite the function to handle nesting 
C:\> function UnrollMe2 { $args[0] } 
C:\> (UnrollMe2 a,b,c | measure).count 
3 

# ditto 
C:\> function UnrollMe3 { $args | %{ $_ } } 
C:\> (UnrollMe3 a,b,c | measure).count 
3 

हालांकि, यह सब कुछ स्पष्ट नहीं होता ...

# as seen earlier - if we're truly returning @(@("a","b","c")) why not count=1? 
C:\> (UnrollMe a,b,c).count 
3 

# our theory must also explain these results: 
C:\> ((UnrollMe a,b,c) | measure).count 
3 
C:\> (@(@("a","b","c")) | measure).count 
3 
C:\> ((UnrollMe a,b,c d) | measure).count 
2 

मैं वहाँ खेल में एक और नियम क्या एक्सट्रपलेशन कर सकते हैं से: अगर आपके पास एक तत्व के साथ एक सरणी है और पार्सर expression mode में है, तो दुभाषिया तत्व को "अनचाहे" करेगा। मैं और अधिक subtleties मैं याद कर रहा हूँ?

+0

WriteObject के समतुल्य लिखें-आउटपुट cmdlet (echo करने के लिए उपनाम) है जो लोग शायद ही कभी उपयोग करते हैं क्योंकि मूल्य stdout स्ट्रीम पर पूरी तरह से आउटपुट होते हैं। –

+0

सच है, यद्यपि लिखने-आउटपुट में एक -अन्यूमेरेट कोलेक्शन पैरामीटर नहीं है जैसे WriteObject (ऑब्जेक्ट, बूल) करता है। –

+0

संबंधित: http://stackoverflow.com/questions/28702588/in-what-conditions-does-powershell-unroll-items-in-the-pipeline/28707054#28707054 – alx9r

उत्तर

11

$ args unrolled है। याद रखें कि फ़ंक्शन पैरामीटर सामान्य रूप से उन्हें अलग करने के लिए स्थान का उपयोग करके पारित किए जाते हैं। जब आप 1,2,3 में पारित आप एक ही तर्क है कि तीन नंबर है कि $ करने के लिए सौंप दिया जाता है की एक सरणी है में से गुजर रहे हैं args [0]:

PS> function UnrollMe { $args } 
PS> UnrollMe 1 2 3 | measure 

Count : 3 

एक समूह के भीतर परिणाम (एक सरणी) लाना अभिव्यक्ति (या subexpression उदाहरण के लिए

PS> ((UnrollMe 1,2,3) | measure).Count 
3 

जो के बराबर है:

PS> ((1,2,3) | measure).Count 
3 

BTW यह नहीं है $()) यह unrolling तो निम्नलिखित वस्तु [] युक्त 1,2,3 UnrollMe द्वारा दिया unrolls के लिए फिर से पात्र बनाती है बस एक तत्व के साथ एक सरणी पर लागू करें।

PS> ((1,2),3) | %{$_.GetType().Name} 
Object[] 
Int32 

कुछ पर एक सरणी उपसूचक (@()) एक सरणी कोई फर्क नहीं पड़ता कि कितनी बार आप इसे लागू कोई प्रभाव नहीं है पहले से ही है कि का उपयोग करना। :-) यदि आप अनलॉकिंग को अल्पविराम ऑपरेटर का उपयोग करना बंद करना चाहते हैं क्योंकि यह हमेशा अनदेखा हो जाने वाला एक और बाहरी सरणी बना देगा। ध्यान दें कि इस परिदृश्य तुम सच में unrolling को नहीं रोकते हैं में, तुम बस unrolling चारों ओर एक बाहरी "आवरण" सरणी है कि अपने मूल सरणी जैसे के बजाय unrolled हो जाता है शुरू करने से काम करते हैं: अंत में

PS> (,(1,2,3) | measure).Count 
1 

, जब आप इस पर अमल :

PS> (UnrollMe a,b,c d) | %{$_.GetType().Name} 
Object[] 
String 

आप देख सकते हैं कि UnrollMe दो आइटम रिटर्न (क, ख, ग) एक सरणी और एक अदिश के रूप में घ के रूप में। उन दो वस्तुओं को अलग-अलग पाइपलाइन भेज दिया जाता है, जिसके परिणामस्वरूप गणना होती है 2.

+0

अच्छी कॉल। स्पष्टीकरण के लिए: मेरे उदाहरण में, $ args केवल एक सरणी नहीं बल्कि सरणी-सरणी है। इसका पहला और एकमात्र तत्व @ (1,2,3) है। –

+0

हम्म, आगे प्रतिबिंब पर यह उत्तर से अधिक प्रश्न उठाता है :) संपादन देखें। –

+0

>> समूहबद्ध अभिव्यक्ति के भीतर परिणाम (एक सरणी) डालना (या उप-अभिव्यक्ति जैसे $()) इसे अनलॉक करने के लिए फिर से योग्य बनाता है। //// उत्कृष्ट सारांश, धन्यवाद। –

1

ऐसा लगता है कि माप-वस्तु कैसे काम करती है और पाइपलाइन के साथ वस्तुओं को कैसे पारित किया जाता है।

जब आप कहते हैं कि

1,2,3 | measure 

आप 3 Int32 वस्तुओं पाइपलाइन पर भेज सकते हैं मापने वस्तु तो प्रत्येक यह पाइपलाइन पर देखता वस्तु मायने रखता है मिलता है।

जब आप "इसे उतारना" अपने समारोह का उपयोग कर, आप पाइपलाइन जो 1 के रूप में उपाय वस्तु मायने रखता है, यह सरणी में वस्तुओं के माध्यम से पुनरावृति करने के लिए कोई प्रयास करता है पर पारित एक सारिणी का वस्तु, के रूप में यहाँ दिखाया गया है:

PS C:\> (measure -input 1,2,3).count 
1 

एक संभावित काम के आसपास करने के लिए "फिर से रोल" पाइपलाइन foreach का उपयोग कर पर सरणी है:

PS C:\> (UnrollMe 1,2,3 | %{$_} | measure).count 
3 
संबंधित मुद्दे

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